initial import
[vuplus_webkit] / Source / WebCore / bindings / v8 / V8Binding.h
1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifndef V8Binding_h
32 #define V8Binding_h
33
34 #include "BindingSecurity.h"
35 #include "DOMDataStore.h"
36 #include "MathExtras.h"
37 #include "PlatformString.h"
38 #include "V8DOMWrapper.h"
39 #include "V8GCController.h"
40 #include "V8HiddenPropertyName.h"
41 #include <wtf/text/AtomicString.h>
42
43 #include <v8.h>
44
45 namespace WebCore {
46
47     class DOMStringList;
48     class EventListener;
49     class EventTarget;
50
51     // FIXME: Remove V8Binding.
52     class V8Binding {
53     };
54     typedef BindingSecurity<V8Binding> V8BindingSecurity;
55
56     class StringCache {
57     public:
58         StringCache() { }
59
60         v8::Local<v8::String> v8ExternalString(StringImpl* stringImpl) 
61         {
62             if (m_lastStringImpl.get() == stringImpl) {
63                 ASSERT(!m_lastV8String.IsNearDeath());
64                 ASSERT(!m_lastV8String.IsEmpty());
65                 return v8::Local<v8::String>::New(m_lastV8String);
66             }
67
68             return v8ExternalStringSlow(stringImpl);
69         }
70
71         void clearOnGC() 
72         {
73             m_lastStringImpl = 0;
74             m_lastV8String.Clear();
75         }
76
77         void remove(StringImpl*);
78
79     private:
80         v8::Local<v8::String> v8ExternalStringSlow(StringImpl*);
81
82         HashMap<StringImpl*, v8::String*> m_stringCache;
83         v8::Persistent<v8::String> m_lastV8String;
84         // Note: RefPtr is a must as we cache by StringImpl* equality, not identity
85         // hence lastStringImpl might be not a key of the cache (in sense of identity)
86         // and hence it's not refed on addition.
87         RefPtr<StringImpl> m_lastStringImpl;
88     };
89
90     class AllowAllocation;
91
92 #ifndef NDEBUG
93     typedef HashMap<v8::Value*, GlobalHandleInfo*> GlobalHandleMap;
94 #endif
95
96     class V8BindingPerIsolateData {
97     public:
98         static V8BindingPerIsolateData* create(v8::Isolate*);
99         static void ensureInitialized(v8::Isolate*);
100         static V8BindingPerIsolateData* get(v8::Isolate* isolate)
101         {
102             ASSERT(isolate->GetData());
103             return static_cast<V8BindingPerIsolateData*>(isolate->GetData()); 
104         }
105
106         static V8BindingPerIsolateData* current()
107         {
108             return get(v8::Isolate::GetCurrent());
109         }
110         static void dispose(v8::Isolate*);
111
112         typedef HashMap<WrapperTypeInfo*, v8::Persistent<v8::FunctionTemplate> > TemplateMap;
113
114         TemplateMap& rawTemplateMap() { return m_rawTemplates; }
115         TemplateMap& templateMap() { return m_templates; }
116         v8::Persistent<v8::String>& toStringName() { return m_toStringName; }
117         v8::Persistent<v8::FunctionTemplate>& toStringTemplate() { return m_toStringTemplate; }
118
119         v8::Persistent<v8::FunctionTemplate>& lazyEventListenerToStringTemplate()
120         {
121             return m_lazyEventListenerToStringTemplate;
122         }
123
124         StringCache* stringCache() { return &m_stringCache; }
125
126         DOMDataList& allStores() { return m_domDataList; }
127
128         V8HiddenPropertyName* hiddenPropertyName() { return &m_hiddenPropertyName; }
129
130         void registerDOMDataStore(DOMDataStore* domDataStore) 
131         {
132             m_domDataList.append(domDataStore);
133         }
134
135         void unregisterDOMDataStore(DOMDataStore* domDataStore)
136         {
137             ASSERT(m_domDataList.find(domDataStore));
138             m_domDataList.remove(m_domDataList.find(domDataStore));
139         }
140
141
142         DOMDataStore* domDataStore() { return m_domDataStore; }
143         // DOMDataStore is owned outside V8BindingPerIsolateData.
144         void setDOMDataStore(DOMDataStore* store) { m_domDataStore = store; }
145
146 #ifndef NDEBUG
147         GlobalHandleMap& globalHandleMap() { return m_globalHandleMap; }
148 #endif
149
150     private:
151         explicit V8BindingPerIsolateData(v8::Isolate*);
152         ~V8BindingPerIsolateData();
153
154         TemplateMap m_rawTemplates;
155         TemplateMap m_templates;
156         v8::Persistent<v8::String> m_toStringName;
157         v8::Persistent<v8::FunctionTemplate> m_toStringTemplate;
158         v8::Persistent<v8::FunctionTemplate> m_lazyEventListenerToStringTemplate;
159         StringCache m_stringCache;
160
161         DOMDataList m_domDataList;
162         DOMDataStore* m_domDataStore;
163
164         V8HiddenPropertyName m_hiddenPropertyName;
165
166         bool m_currentAllocationsAllowed;
167         friend class AllowAllocation;
168
169 #ifndef NDEBUG
170         GlobalHandleMap m_globalHandleMap;
171 #endif
172     };
173
174     class AllowAllocation {
175     public:
176         AllowAllocation()
177         {
178             V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
179             m_previous = data->m_currentAllocationsAllowed;
180             data->m_currentAllocationsAllowed = true;
181         }
182
183         ~AllowAllocation()
184         {
185             V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
186             data->m_currentAllocationsAllowed = m_previous;
187         }
188
189         static bool current() { return V8BindingPerIsolateData::current()->m_currentAllocationsAllowed; }
190
191     private:
192         bool m_previous;
193     };
194
195     class SafeAllocation {
196     public:
197         static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>);
198         static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::ObjectTemplate>);
199         static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]);
200     };
201
202     v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function)
203     {
204         if (function.IsEmpty())
205             return v8::Local<v8::Object>();
206         AllowAllocation allow;
207         return function->NewInstance();
208     }
209
210     v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::ObjectTemplate> objectTemplate)
211     {
212         if (objectTemplate.IsEmpty())
213             return v8::Local<v8::Object>();
214         AllowAllocation allow;
215         return objectTemplate->NewInstance();
216     }
217
218     v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[])
219     {
220         if (function.IsEmpty())
221             return v8::Local<v8::Object>();
222         AllowAllocation allow;
223         return function->NewInstance(argc, argv);
224     }
225
226
227
228     enum ExternalMode {
229         Externalize,
230         DoNotExternalize
231     };
232
233     template <typename StringType>
234     StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external);
235
236     // Convert v8 types to a WTF::String. If the V8 string is not already
237     // an external string then it is transformed into an external string at this
238     // point to avoid repeated conversions.
239     inline String v8StringToWebCoreString(v8::Handle<v8::String> v8String)
240     {
241         return v8StringToWebCoreString<String>(v8String, Externalize);
242     }
243     String v8NonStringValueToWebCoreString(v8::Handle<v8::Value>);
244     String v8ValueToWebCoreString(v8::Handle<v8::Value> value);
245
246     // Convert v8 types to a WTF::AtomicString.
247     inline AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String)
248     {
249         return v8StringToWebCoreString<AtomicString>(v8String, Externalize);
250     }
251     AtomicString v8NonStringValueToAtomicWebCoreString(v8::Handle<v8::Value>);
252     AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> value);
253
254     // Return a V8 external string that shares the underlying buffer with the given
255     // WebCore string. The reference counting mechanism is used to keep the
256     // underlying buffer alive while the string is still live in the V8 engine.
257     inline v8::Local<v8::String> v8ExternalString(const String& string)
258     {
259         StringImpl* stringImpl = string.impl();
260         if (!stringImpl)
261             return v8::String::Empty();
262
263         V8BindingPerIsolateData* data = V8BindingPerIsolateData::current();
264         return data->stringCache()->v8ExternalString(stringImpl);
265     }
266
267     // Convert a string to a V8 string.
268     inline v8::Handle<v8::String> v8String(const String& string)
269     {
270         return v8ExternalString(string);
271     }
272
273     // Enables caching v8 wrappers created for WTF::StringImpl.  Currently this cache requires
274     // all the calls (both to convert WTF::String to v8::String and to GC the handle)
275     // to be performed on the main thread.
276     void enableStringImplCache();
277
278     // Convert a value to a 32-bit integer.  The conversion fails if the
279     // value cannot be converted to an integer or converts to nan or to an infinity.
280     int toInt32(v8::Handle<v8::Value> value, bool& ok);
281
282     // Convert a value to a 32-bit integer assuming the conversion cannot fail.
283     inline int toInt32(v8::Handle<v8::Value> value)
284     {
285         bool ok;
286         return toInt32(value, ok);
287     }
288
289     // Convert a value to a 32-bit unsigned integer.  The conversion fails if the
290     // value cannot be converted to an unsigned integer or converts to nan or to an infinity.
291     uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok);
292
293     // Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail.
294     inline uint32_t toUInt32(v8::Handle<v8::Value> value)
295     {
296         bool ok;
297         return toUInt32(value, ok);
298     }
299
300     inline float toFloat(v8::Local<v8::Value> value)
301     {
302         return static_cast<float>(value->NumberValue());
303     }
304
305     inline long long toInt64(v8::Local<v8::Value> value)
306     {
307         return static_cast<long long>(value->IntegerValue());
308     }
309
310     // FIXME: Drop this in favor of the type specific v8ValueToWebCoreString when we rework the code generation.
311     inline String toWebCoreString(v8::Handle<v8::Value> object)
312     {
313         return v8ValueToWebCoreString(object);
314     }
315
316     String toWebCoreString(const v8::Arguments&, int index);
317
318     // The string returned by this function is still owned by the argument
319     // and will be deallocated when the argument is deallocated.
320     inline const uint16_t* fromWebCoreString(const String& str)
321     {
322         return reinterpret_cast<const uint16_t*>(str.characters());
323     }
324
325     bool isUndefinedOrNull(v8::Handle<v8::Value> value);
326
327     // Returns true if the provided object is to be considered a 'host object', as used in the
328     // HTML5 structured clone algorithm.
329     bool isHostObject(v8::Handle<v8::Object>);
330
331     v8::Handle<v8::Boolean> v8Boolean(bool value);
332
333     String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value);
334
335     AtomicString toAtomicWebCoreStringWithNullCheck(v8::Handle<v8::Value> value);
336
337     String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value);
338
339     v8::Handle<v8::String> v8UndetectableString(const String& str);
340
341     v8::Handle<v8::Value> v8StringOrNull(const String& str);
342
343     v8::Handle<v8::Value> v8StringOrUndefined(const String& str);
344
345     v8::Handle<v8::Value> v8StringOrFalse(const String& str);
346
347     double toWebCoreDate(v8::Handle<v8::Value> object);
348
349     v8::Handle<v8::Value> v8DateOrNull(double value);
350
351     v8::Persistent<v8::FunctionTemplate> createRawTemplate();
352
353     struct BatchedAttribute;
354     struct BatchedCallback;
355
356     v8::Local<v8::Signature> configureTemplate(v8::Persistent<v8::FunctionTemplate>,
357                                                const char* interfaceName,
358                                                v8::Persistent<v8::FunctionTemplate> parentClass,
359                                                int fieldCount,
360                                                const BatchedAttribute*,
361                                                size_t attributeCount,
362                                                const BatchedCallback*,
363                                                size_t callbackCount);
364
365     v8::Handle<v8::Value> getElementStringAttr(const v8::AccessorInfo&,
366                                                const QualifiedName&);
367     void setElementStringAttr(const v8::AccessorInfo&,
368                               const QualifiedName&,
369                               v8::Local<v8::Value>);
370
371
372     v8::Persistent<v8::String> getToStringName();
373     v8::Persistent<v8::FunctionTemplate> getToStringTemplate();
374
375     String int32ToWebCoreString(int value);
376
377     PassRefPtr<DOMStringList> v8ValueToWebCoreDOMStringList(v8::Handle<v8::Value>);
378
379     class V8ParameterBase {
380     public:
381         operator String() { return toString<String>(); }
382         operator AtomicString() { return toString<AtomicString>(); }
383
384     protected:
385         V8ParameterBase(v8::Local<v8::Value> object) : m_v8Object(object), m_mode(Externalize), m_string() { }
386
387         bool prepareBase()
388         {
389             if (m_v8Object.IsEmpty())
390                 return true;
391
392             if (LIKELY(m_v8Object->IsString()))
393                 return true;
394
395             if (LIKELY(m_v8Object->IsInt32())) {
396                 setString(int32ToWebCoreString(m_v8Object->Int32Value()));
397                 return true;
398             }
399
400             m_mode = DoNotExternalize;
401             v8::TryCatch block;
402             m_v8Object = m_v8Object->ToString();
403             // Handle the case where an exception is thrown as part of invoking toString on the object.
404             if (block.HasCaught()) {
405                 block.ReThrow();
406                 return false;
407             }
408             return true;
409         }
410
411         v8::Local<v8::Value> object() { return m_v8Object; }
412
413         void setString(const String& string)
414         {
415             m_string = string;
416             m_v8Object.Clear(); // To signal that String is ready.
417         }
418
419      private:
420         v8::Local<v8::Value> m_v8Object;
421         ExternalMode m_mode;
422         String m_string;
423
424         template <class StringType>
425         StringType toString()
426         {
427             if (LIKELY(!m_v8Object.IsEmpty()))
428                 return v8StringToWebCoreString<StringType>(m_v8Object.As<v8::String>(), m_mode);
429
430             return StringType(m_string);
431         }
432     };
433
434     // V8Parameter is an adapter class that converts V8 values to Strings
435     // or AtomicStrings as appropriate, using multiple typecast operators.
436     enum V8ParameterMode {
437         DefaultMode,
438         WithNullCheck,
439         WithUndefinedOrNullCheck
440     };
441     template <V8ParameterMode MODE = DefaultMode>
442     class V8Parameter: public V8ParameterBase {
443     public:
444         V8Parameter(v8::Local<v8::Value> object) : V8ParameterBase(object) { }
445         V8Parameter(v8::Local<v8::Value> object, bool) : V8ParameterBase(object) { prepare(); }
446
447         bool prepare();
448     };
449
450     template<> inline bool V8Parameter<DefaultMode>::prepare()
451     {
452         return V8ParameterBase::prepareBase();
453     }
454
455     template<> inline bool V8Parameter<WithNullCheck>::prepare()
456     {
457         if (object().IsEmpty() || object()->IsNull()) {
458             setString(String());
459             return true;
460         }
461
462         return V8ParameterBase::prepareBase();
463     }
464
465     template<> inline bool V8Parameter<WithUndefinedOrNullCheck>::prepare()
466     {
467         if (object().IsEmpty() || object()->IsNull() || object()->IsUndefined()) {
468             setString(String());
469             return true;
470         }
471
472         return V8ParameterBase::prepareBase();
473     }
474
475     enum ParameterMissingPolicy {
476         MissingIsUndefined,
477         MissingIsEmpty
478     };
479
480 } // namespace WebCore
481
482 #endif // V8Binding_h