• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * Copyright (C) 2012 Ericsson AB. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 
32 #ifndef V8Binding_h
33 #define V8Binding_h
34 
35 #include "bindings/v8/DOMWrapperWorld.h"
36 #include "bindings/v8/ExceptionMessages.h"
37 #include "bindings/v8/V8BindingMacros.h"
38 #include "bindings/v8/V8PerIsolateData.h"
39 #include "bindings/v8/V8StringResource.h"
40 #include "bindings/v8/V8ThrowException.h"
41 #include "bindings/v8/V8ValueCache.h"
42 #include "wtf/MathExtras.h"
43 #include "wtf/text/AtomicString.h"
44 #include <v8.h>
45 
46 namespace WebCore {
47 
48     class DOMWindow;
49     class Document;
50     class Frame;
51     class NodeFilter;
52     class ExecutionContext;
53     class ScriptWrappable;
54     class XPathNSResolver;
55 
56     const int kMaxRecursionDepth = 22;
57 
58     // Schedule a DOM exception to be thrown, if the exception code is different
59     // from zero.
60     v8::Handle<v8::Value> setDOMException(int, v8::Isolate*);
61     v8::Handle<v8::Value> setDOMException(int, const String&, v8::Isolate*);
62 
63     // Schedule a JavaScript error to be thrown.
64     v8::Handle<v8::Value> throwError(V8ErrorType, const String&, v8::Isolate*);
65 
66     // Schedule a JavaScript error to be thrown.
67     v8::Handle<v8::Value> throwError(v8::Handle<v8::Value>, v8::Isolate*);
68 
69     // A helper for throwing JavaScript TypeError.
70     v8::Handle<v8::Value> throwTypeError(const String&, v8::Isolate*);
71 
72     // FIXME: Remove this once we kill its callers.
73     v8::Handle<v8::Value> throwUninformativeAndGenericTypeError(v8::Isolate*);
74 
75     v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator();
76 
77     v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value>, uint32_t& length, v8::Isolate*);
78 
argumentOrNull(const v8::FunctionCallbackInfo<v8::Value> & info,int index)79     inline v8::Handle<v8::Value> argumentOrNull(const v8::FunctionCallbackInfo<v8::Value>& info, int index)
80     {
81         return index >= info.Length() ? v8::Local<v8::Value>() : info[index];
82     }
83 
84     template<typename CallbackInfo, typename V>
v8SetReturnValue(const CallbackInfo & info,V v)85     inline void v8SetReturnValue(const CallbackInfo& info, V v)
86     {
87         info.GetReturnValue().Set(v);
88     }
89 
90     template<typename CallbackInfo>
v8SetReturnValueBool(const CallbackInfo & info,bool v)91     inline void v8SetReturnValueBool(const CallbackInfo& info, bool v)
92     {
93         info.GetReturnValue().Set(v);
94     }
95 
96     template<typename CallbackInfo>
v8SetReturnValueInt(const CallbackInfo & info,int v)97     inline void v8SetReturnValueInt(const CallbackInfo& info, int v)
98     {
99         info.GetReturnValue().Set(v);
100     }
101 
102     template<typename CallbackInfo>
v8SetReturnValueUnsigned(const CallbackInfo & info,unsigned v)103     inline void v8SetReturnValueUnsigned(const CallbackInfo& info, unsigned v)
104     {
105         info.GetReturnValue().Set(v);
106     }
107 
108     template<typename CallbackInfo>
v8SetReturnValueNull(const CallbackInfo & info)109     inline void v8SetReturnValueNull(const CallbackInfo& info)
110     {
111         info.GetReturnValue().SetNull();
112     }
113 
114     template<typename CallbackInfo>
v8SetReturnValueUndefined(const CallbackInfo & info)115     inline void v8SetReturnValueUndefined(const CallbackInfo& info)
116     {
117         info.GetReturnValue().SetUndefined();
118     }
119 
120     template<typename CallbackInfo>
v8SetReturnValueEmptyString(const CallbackInfo & info)121     inline void v8SetReturnValueEmptyString(const CallbackInfo& info)
122     {
123         info.GetReturnValue().SetEmptyString();
124     }
125 
126     template <class CallbackInfo>
v8SetReturnValueString(const CallbackInfo & info,const String & string,v8::Isolate * isolate)127     inline void v8SetReturnValueString(const CallbackInfo& info, const String& string, v8::Isolate* isolate)
128     {
129         if (string.isNull()) {
130             v8SetReturnValueEmptyString(info);
131             return;
132         }
133         V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl());
134     }
135 
136     template <class CallbackInfo>
v8SetReturnValueStringOrNull(const CallbackInfo & info,const String & string,v8::Isolate * isolate)137     inline void v8SetReturnValueStringOrNull(const CallbackInfo& info, const String& string, v8::Isolate* isolate)
138     {
139         if (string.isNull()) {
140             v8SetReturnValueNull(info);
141             return;
142         }
143         V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl());
144     }
145 
146     template <class CallbackInfo>
v8SetReturnValueStringOrUndefined(const CallbackInfo & info,const String & string,v8::Isolate * isolate)147     inline void v8SetReturnValueStringOrUndefined(const CallbackInfo& info, const String& string, v8::Isolate* isolate)
148     {
149         if (string.isNull()) {
150             v8SetReturnValueUndefined(info);
151             return;
152         }
153         V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl());
154     }
155 
156     // Convert v8::String to a WTF::String. If the V8 string is not already
157     // an external string then it is transformed into an external string at this
158     // point to avoid repeated conversions.
toCoreString(v8::Handle<v8::String> value)159     inline String toCoreString(v8::Handle<v8::String> value)
160     {
161         return v8StringToWebCoreString<String>(value, Externalize);
162     }
163 
toCoreStringWithNullCheck(v8::Handle<v8::String> value)164     inline String toCoreStringWithNullCheck(v8::Handle<v8::String> value)
165     {
166         if (value.IsEmpty() || value->IsNull())
167             return String();
168         return toCoreString(value);
169     }
170 
toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::String> value)171     inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::String> value)
172     {
173         if (value.IsEmpty() || value->IsNull() || value->IsUndefined())
174             return String();
175         return toCoreString(value);
176     }
177 
toCoreAtomicString(v8::Handle<v8::String> value)178     inline AtomicString toCoreAtomicString(v8::Handle<v8::String> value)
179     {
180         return v8StringToWebCoreString<AtomicString>(value, Externalize);
181     }
182 
183     // This method will return a null String if the v8::Value does not contain a v8::String.
184     // It will not call ToString() on the v8::Value. If you want ToString() to be called,
185     // please use the V8TRYCATCH_FOR_V8STRINGRESOURCE_*() macros instead.
toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::Value> value)186     inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::Value> value)
187     {
188         if (value.IsEmpty() || !value->IsString())
189             return String();
190 
191         return toCoreString(value.As<v8::String>());
192     }
193 
194     // Convert a string to a V8 string.
195     // Return a V8 external string that shares the underlying buffer with the given
196     // WebCore string. The reference counting mechanism is used to keep the
197     // underlying buffer alive while the string is still live in the V8 engine.
v8String(v8::Isolate * isolate,const String & string)198     inline v8::Handle<v8::String> v8String(v8::Isolate* isolate, const String& string)
199     {
200         if (string.isNull())
201             return v8::String::Empty(isolate);
202         return V8PerIsolateData::from(isolate)->stringCache()->v8ExternalString(string.impl(), isolate);
203     }
204 
v8Undefined()205     inline v8::Handle<v8::Value> v8Undefined()
206     {
207         return v8::Handle<v8::Value>();
208     }
209 
210     template <class T>
211     struct V8ValueTraits {
arrayV8ValueV8ValueTraits212         static inline v8::Handle<v8::Value> arrayV8Value(const T& value, v8::Isolate* isolate)
213         {
214             return toV8(WTF::getPtr(value), v8::Handle<v8::Object>(), isolate);
215         }
216     };
217 
218     template<>
219     struct V8ValueTraits<String> {
220         static inline v8::Handle<v8::Value> arrayV8Value(const String& value, v8::Isolate* isolate)
221         {
222             return v8String(isolate, value);
223         }
224     };
225 
226     template<>
227     struct V8ValueTraits<unsigned> {
228         static inline v8::Handle<v8::Value> arrayV8Value(const unsigned& value, v8::Isolate* isolate)
229         {
230             return v8::Integer::NewFromUnsigned(value, isolate);
231         }
232     };
233 
234     template<>
235     struct V8ValueTraits<unsigned long> {
236         static inline v8::Handle<v8::Value> arrayV8Value(const unsigned long& value, v8::Isolate* isolate)
237         {
238             return v8::Integer::NewFromUnsigned(value, isolate);
239         }
240     };
241 
242     template<>
243     struct V8ValueTraits<float> {
244         static inline v8::Handle<v8::Value> arrayV8Value(const float& value, v8::Isolate* isolate)
245         {
246             return v8::Number::New(isolate, value);
247         }
248     };
249 
250     template<>
251     struct V8ValueTraits<double> {
252         static inline v8::Handle<v8::Value> arrayV8Value(const double& value, v8::Isolate* isolate)
253         {
254             return v8::Number::New(isolate, value);
255         }
256     };
257 
258     template<typename T, size_t inlineCapacity>
259     v8::Handle<v8::Value> v8Array(const Vector<T, inlineCapacity>& iterator, v8::Isolate* isolate)
260     {
261         v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size());
262         int index = 0;
263         typename Vector<T, inlineCapacity>::const_iterator end = iterator.end();
264         typedef V8ValueTraits<T> TraitsType;
265         for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter)
266             result->Set(v8::Integer::New(index++, isolate), TraitsType::arrayV8Value(*iter, isolate));
267         return result;
268     }
269 
270     // Conversion flags, used in toIntXX/toUIntXX.
271     enum IntegerConversionConfiguration {
272         NormalConversion,
273         EnforceRange,
274         Clamp
275     };
276 
277     // Convert a value to a 8-bit signed integer. The conversion fails if the
278     // value cannot be converted to a number or the range violated per WebIDL:
279     // http://www.w3.org/TR/WebIDL/#es-byte
280     int8_t toInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
281     inline int8_t toInt8(v8::Handle<v8::Value> value, bool& ok) { return toInt8(value, NormalConversion, ok); }
282 
283     // Convert a value to a 8-bit integer assuming the conversion cannot fail.
284     inline int8_t toInt8(v8::Handle<v8::Value> value)
285     {
286         bool ok;
287         return toInt8(value, NormalConversion, ok);
288     }
289 
290     // Convert a value to a 8-bit unsigned integer. The conversion fails if the
291     // value cannot be converted to a number or the range violated per WebIDL:
292     // http://www.w3.org/TR/WebIDL/#es-octet
293     uint8_t toUInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
294     inline uint8_t toUInt8(v8::Handle<v8::Value> value, bool& ok) { return toUInt8(value, NormalConversion, ok); }
295 
296     // Convert a value to a 8-bit unsigned integer assuming the conversion cannot fail.
297     inline uint8_t toUInt8(v8::Handle<v8::Value> value)
298     {
299         bool ok;
300         return toUInt8(value, NormalConversion, ok);
301     }
302 
303     // Convert a value to a 16-bit signed integer. The conversion fails if the
304     // value cannot be converted to a number or the range violated per WebIDL:
305     // http://www.w3.org/TR/WebIDL/#es-short
306     int16_t toInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
307     inline int16_t toInt16(v8::Handle<v8::Value> value, bool& ok) { return toInt16(value, NormalConversion, ok); }
308 
309     // Convert a value to a 16-bit integer assuming the conversion cannot fail.
310     inline int16_t toInt16(v8::Handle<v8::Value> value)
311     {
312         bool ok;
313         return toInt16(value, NormalConversion, ok);
314     }
315 
316     // Convert a value to a 16-bit unsigned integer. The conversion fails if the
317     // value cannot be converted to a number or the range violated per WebIDL:
318     // http://www.w3.org/TR/WebIDL/#es-unsigned-short
319     uint16_t toUInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
320     inline uint16_t toUInt16(v8::Handle<v8::Value> value, bool& ok) { return toUInt16(value, NormalConversion, ok); }
321 
322     // Convert a value to a 16-bit unsigned integer assuming the conversion cannot fail.
323     inline uint16_t toUInt16(v8::Handle<v8::Value> value)
324     {
325         bool ok;
326         return toUInt16(value, NormalConversion, ok);
327     }
328 
329     // Convert a value to a 32-bit signed integer. The conversion fails if the
330     // value cannot be converted to a number or the range violated per WebIDL:
331     // http://www.w3.org/TR/WebIDL/#es-long
332     int32_t toInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
333     inline int32_t toInt32(v8::Handle<v8::Value> value, bool& ok) { return toInt32(value, NormalConversion, ok); }
334 
335     // Convert a value to a 32-bit integer assuming the conversion cannot fail.
336     inline int32_t toInt32(v8::Handle<v8::Value> value)
337     {
338         bool ok;
339         return toInt32(value, NormalConversion, ok);
340     }
341 
342     // Convert a value to a 32-bit unsigned integer. The conversion fails if the
343     // value cannot be converted to a number or the range violated per WebIDL:
344     // http://www.w3.org/TR/WebIDL/#es-unsigned-long
345     uint32_t toUInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
346     inline uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok) { return toUInt32(value, NormalConversion, ok); }
347 
348     // Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail.
349     inline uint32_t toUInt32(v8::Handle<v8::Value> value)
350     {
351         bool ok;
352         return toUInt32(value, NormalConversion, ok);
353     }
354 
355     // Convert a value to a 64-bit signed integer. The conversion fails if the
356     // value cannot be converted to a number or the range violated per WebIDL:
357     // http://www.w3.org/TR/WebIDL/#es-long-long
358     int64_t toInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
359 
360     // Convert a value to a 64-bit integer assuming the conversion cannot fail.
361     inline int64_t toInt64(v8::Handle<v8::Value> value)
362     {
363         bool ok;
364         return toInt64(value, NormalConversion, ok);
365     }
366 
367     // Convert a value to a 64-bit unsigned integer. The conversion fails if the
368     // value cannot be converted to a number or the range violated per WebIDL:
369     // http://www.w3.org/TR/WebIDL/#es-unsigned-long-long
370     uint64_t toUInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
371 
372     // Convert a value to a 64-bit unsigned integer assuming the conversion cannot fail.
373     inline uint64_t toUInt64(v8::Handle<v8::Value> value)
374     {
375         bool ok;
376         return toUInt64(value, NormalConversion, ok);
377     }
378 
379     inline float toFloat(v8::Local<v8::Value> value)
380     {
381         return static_cast<float>(value->NumberValue());
382     }
383 
384     WrapperWorldType worldType(v8::Isolate*);
385     WrapperWorldType worldTypeInMainThread(v8::Isolate*);
386 
387     DOMWrapperWorld* isolatedWorldForIsolate(v8::Isolate*);
388 
389     template<class T> struct NativeValueTraits;
390 
391     template<>
392     struct NativeValueTraits<String> {
393         static inline String nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate)
394         {
395             V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, value, String());
396             return stringValue;
397         }
398     };
399 
400     template<>
401     struct NativeValueTraits<unsigned> {
402         static inline unsigned nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate)
403         {
404             return toUInt32(value);
405         }
406     };
407 
408     template<>
409     struct NativeValueTraits<float> {
410         static inline float nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate)
411         {
412             return static_cast<float>(value->NumberValue());
413         }
414     };
415 
416     template<>
417     struct NativeValueTraits<double> {
418         static inline double nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate)
419         {
420             return static_cast<double>(value->NumberValue());
421         }
422     };
423 
424     template<>
425     struct NativeValueTraits<v8::Handle<v8::Value> > {
426         static inline v8::Handle<v8::Value> nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate)
427         {
428             return value;
429         }
430     };
431 
432     // Converts a JavaScript value to an array as per the Web IDL specification:
433     // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array
434     template <class T, class V8T>
435     Vector<RefPtr<T> > toRefPtrNativeArrayUnchecked(v8::Local<v8::Value> v8Value, uint32_t length, v8::Isolate* isolate, bool* success = 0)
436     {
437         Vector<RefPtr<T> > result;
438         result.reserveInitialCapacity(length);
439         v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value);
440         for (uint32_t i = 0; i < length; ++i) {
441             v8::Handle<v8::Value> element = object->Get(i);
442 
443             if (V8T::hasInstance(element, isolate, worldType(isolate))) {
444                 v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element);
445                 result.uncheckedAppend(V8T::toNative(elementObject));
446             } else {
447                 if (success)
448                     *success = false;
449                 throwTypeError("Invalid Array element type", isolate);
450                 return Vector<RefPtr<T> >();
451             }
452         }
453         return result;
454     }
455 
456     template <class T, class V8T>
457     Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, bool* success = 0)
458     {
459         if (success)
460             *success = true;
461 
462         v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value));
463         uint32_t length = 0;
464         if (value->IsArray()) {
465             length = v8::Local<v8::Array>::Cast(v8Value)->Length();
466         } else if (toV8Sequence(value, length, isolate).IsEmpty()) {
467             throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate);
468             return Vector<RefPtr<T> >();
469         }
470 
471         return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success);
472     }
473 
474     template <class T, class V8T>
475     Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, const String& propertyName, v8::Isolate* isolate, bool* success = 0)
476     {
477         if (success)
478             *success = true;
479 
480         v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value));
481         uint32_t length = 0;
482         if (value->IsArray()) {
483             length = v8::Local<v8::Array>::Cast(v8Value)->Length();
484         } else if (toV8Sequence(value, length, isolate).IsEmpty()) {
485             throwTypeError(ExceptionMessages::notASequenceTypeProperty(propertyName), isolate);
486             return Vector<RefPtr<T> >();
487         }
488 
489         return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success);
490     }
491 
492     // Converts a JavaScript value to an array as per the Web IDL specification:
493     // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array
494     template <class T>
495     Vector<T> toNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate)
496     {
497         v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value));
498         uint32_t length = 0;
499         if (value->IsArray()) {
500             length = v8::Local<v8::Array>::Cast(v8Value)->Length();
501         } else if (toV8Sequence(value, length, isolate).IsEmpty()) {
502             throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate);
503             return Vector<T>();
504         }
505 
506         Vector<T> result;
507         result.reserveInitialCapacity(length);
508         typedef NativeValueTraits<T> TraitsType;
509         v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value);
510         for (uint32_t i = 0; i < length; ++i)
511             result.uncheckedAppend(TraitsType::nativeValue(object->Get(i), isolate));
512         return result;
513     }
514 
515     template <class T>
516     Vector<T> toNativeArguments(const v8::FunctionCallbackInfo<v8::Value>& info, int startIndex)
517     {
518         ASSERT(startIndex <= info.Length());
519         Vector<T> result;
520         typedef NativeValueTraits<T> TraitsType;
521         int length = info.Length();
522         result.reserveInitialCapacity(length);
523         for (int i = startIndex; i < length; ++i)
524             result.uncheckedAppend(TraitsType::nativeValue(info[i], info.GetIsolate()));
525         return result;
526     }
527 
528     // Validates that the passed object is a sequence type per WebIDL spec
529     // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-sequence
530     inline v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value> value, uint32_t& length, v8::Isolate* isolate)
531     {
532         // Attempt converting to a sequence if the value is not already an array but is
533         // any kind of object except for a native Date object or a native RegExp object.
534         ASSERT(!value->IsArray());
535         // FIXME: Do we really need to special case Date and RegExp object?
536         // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22806
537         if (!value->IsObject() || value->IsDate() || value->IsRegExp()) {
538             // The caller is responsible for reporting a TypeError.
539             return v8Undefined();
540         }
541 
542         v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value));
543         v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value);
544         v8::Local<v8::String> lengthSymbol = v8::String::NewFromUtf8(isolate, "length", v8::String::kInternalizedString, 6);
545 
546         // FIXME: The specification states that the length property should be used as fallback, if value
547         // is not a platform object that supports indexed properties. If it supports indexed properties,
548         // length should actually be one greater than value’s maximum indexed property index.
549         V8TRYCATCH(v8::Local<v8::Value>, lengthValue, object->Get(lengthSymbol));
550 
551         if (lengthValue->IsUndefined() || lengthValue->IsNull()) {
552             // The caller is responsible for reporting a TypeError.
553             return v8Undefined();
554         }
555 
556         V8TRYCATCH(uint32_t, sequenceLength, lengthValue->Int32Value());
557         length = sequenceLength;
558 
559         return v8Value;
560     }
561 
562     PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value>, v8::Isolate*);
563 
564     inline bool isUndefinedOrNull(v8::Handle<v8::Value> value)
565     {
566         return value->IsNull() || value->IsUndefined();
567     }
568 
569     // Returns true if the provided object is to be considered a 'host object', as used in the
570     // HTML5 structured clone algorithm.
571     inline bool isHostObject(v8::Handle<v8::Object> object)
572     {
573         // If the object has any internal fields, then we won't be able to serialize or deserialize
574         // them; conveniently, this is also a quick way to detect DOM wrapper objects, because
575         // the mechanism for these relies on data stored in these fields. We should
576         // catch external array data as a special case.
577         return object->InternalFieldCount() || object->HasIndexedPropertiesInExternalArrayData();
578     }
579 
580     inline v8::Handle<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate)
581     {
582         return value ? v8::True(isolate) : v8::False(isolate);
583     }
584 
585     // Since v8Boolean(value, isolate) crashes if we pass a null isolate,
586     // we need to use v8BooleanWithCheck(value, isolate) if an isolate can be null.
587     //
588     // FIXME: Remove all null isolates from V8 bindings, and remove v8BooleanWithCheck(value, isolate).
589     inline v8::Handle<v8::Boolean> v8BooleanWithCheck(bool value, v8::Isolate* isolate)
590     {
591         return isolate ? v8Boolean(value, isolate) : v8Boolean(value, v8::Isolate::GetCurrent());
592     }
593 
594     inline double toWebCoreDate(v8::Handle<v8::Value> object)
595     {
596         if (object->IsDate())
597             return v8::Handle<v8::Date>::Cast(object)->ValueOf();
598         if (object->IsNumber())
599             return object->NumberValue();
600         return std::numeric_limits<double>::quiet_NaN();
601     }
602 
603     inline v8::Handle<v8::Value> v8DateOrNull(double value, v8::Isolate* isolate)
604     {
605         ASSERT(isolate);
606         return std::isfinite(value) ? v8::Date::New(isolate, value) : v8::Handle<v8::Value>::Cast(v8::Null(isolate));
607     }
608 
609     inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str)
610     {
611         ASSERT(isolate);
612         return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, strlen(str));
613     }
614 
615     inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str, size_t length)
616     {
617         ASSERT(isolate);
618         return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, length);
619     }
620 
621 
622     v8::Handle<v8::FunctionTemplate> createRawTemplate(v8::Isolate*);
623 
624     PassRefPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value>, v8::Isolate*);
625 
626     v8::Handle<v8::Object> toInnerGlobalObject(v8::Handle<v8::Context>);
627     DOMWindow* toDOMWindow(v8::Handle<v8::Context>);
628     ExecutionContext* toExecutionContext(v8::Handle<v8::Context>);
629 
630     DOMWindow* activeDOMWindow();
631     ExecutionContext* activeExecutionContext();
632     DOMWindow* firstDOMWindow();
633     Document* currentDocument();
634 
635     // Returns the context associated with a ExecutionContext.
636     v8::Local<v8::Context> toV8Context(ExecutionContext*, DOMWrapperWorld*);
637 
638     // Returns the frame object of the window object associated with
639     // a context, if the window is currently being displayed in the Frame.
640     Frame* toFrameIfNotDetached(v8::Handle<v8::Context>);
641 
642     inline DOMWrapperWorld* isolatedWorldForEnteredContext(v8::Isolate* isolate)
643     {
644         v8::Handle<v8::Context> context = isolate->GetEnteredContext();
645         if (context.IsEmpty())
646             return 0;
647         return DOMWrapperWorld::isolatedWorld(context);
648     }
649 
650     // FIXME: This will be soon embedded in the generated code.
651     template<class Collection> static void indexedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
652     {
653         Collection* collection = reinterpret_cast<Collection*>(info.Holder()->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex));
654         int length = collection->length();
655         v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), length);
656         for (int i = 0; i < length; ++i) {
657             // FIXME: Do we need to check that the item function returns a non-null value for this index?
658             v8::Handle<v8::Integer> integer = v8::Integer::New(i, info.GetIsolate());
659             properties->Set(integer, integer);
660         }
661         v8SetReturnValue(info, properties);
662     }
663 
664     // If the current context causes out of memory, JavaScript setting
665     // is disabled and it returns true.
666     bool handleOutOfMemory();
667     v8::Local<v8::Value> handleMaxRecursionDepthExceeded(v8::Isolate*);
668 
669     void crashIfV8IsDead();
670 
671     template <class T>
672     v8::Handle<T> unsafeHandleFromRawValue(const T* value)
673     {
674         const v8::Handle<T>* handle = reinterpret_cast<const v8::Handle<T>*>(&value);
675         return *handle;
676     }
677 
678     // Attaches |environment| to |function| and returns it.
679     inline v8::Local<v8::Function> createClosure(v8::FunctionCallback function, v8::Handle<v8::Value> environment, v8::Isolate* isolate)
680     {
681         return v8::Function::New(isolate, function, environment);
682     }
683 
684     v8::Local<v8::Value> getHiddenValueFromMainWorldWrapper(v8::Isolate*, ScriptWrappable*, v8::Handle<v8::String> key);
685 
686     v8::Isolate* mainThreadIsolate();
687     v8::Isolate* toIsolate(ExecutionContext*);
688     v8::Isolate* toIsolate(Frame*);
689 
690     // Can only be called by blink::initialize
691     void setMainThreadIsolate(v8::Isolate*);
692 
693     // Converts a DOM object to a v8 value.
694     // This is a no-inline version of toV8(). If you want to call toV8()
695     // without creating #include cycles, you can use this function instead.
696     // Each specialized implementation will be generated.
697     template<typename T>
698     v8::Handle<v8::Value> toV8NoInline(T* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*);
699 } // namespace WebCore
700 
701 #endif // V8Binding_h
702