Home | History | Annotate | Download | only in v8
      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 
     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>
     85     inline void v8SetReturnValue(const CallbackInfo& info, V v)
     86     {
     87         info.GetReturnValue().Set(v);
     88     }
     89 
     90     template<typename CallbackInfo>
     91     inline void v8SetReturnValueBool(const CallbackInfo& info, bool v)
     92     {
     93         info.GetReturnValue().Set(v);
     94     }
     95 
     96     template<typename CallbackInfo>
     97     inline void v8SetReturnValueInt(const CallbackInfo& info, int v)
     98     {
     99         info.GetReturnValue().Set(v);
    100     }
    101 
    102     template<typename CallbackInfo>
    103     inline void v8SetReturnValueUnsigned(const CallbackInfo& info, unsigned v)
    104     {
    105         info.GetReturnValue().Set(v);
    106     }
    107 
    108     template<typename CallbackInfo>
    109     inline void v8SetReturnValueNull(const CallbackInfo& info)
    110     {
    111         info.GetReturnValue().SetNull();
    112     }
    113 
    114     template<typename CallbackInfo>
    115     inline void v8SetReturnValueUndefined(const CallbackInfo& info)
    116     {
    117         info.GetReturnValue().SetUndefined();
    118     }
    119 
    120     template<typename CallbackInfo>
    121     inline void v8SetReturnValueEmptyString(const CallbackInfo& info)
    122     {
    123         info.GetReturnValue().SetEmptyString();
    124     }
    125 
    126     template <class CallbackInfo>
    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>
    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>
    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.
    159     inline String toCoreString(v8::Handle<v8::String> value)
    160     {
    161         return v8StringToWebCoreString<String>(value, Externalize);
    162     }
    163 
    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 
    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 
    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.
    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.
    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 
    205     inline v8::Handle<v8::Value> v8Undefined()
    206     {
    207         return v8::Handle<v8::Value>();
    208     }
    209 
    210     template <class T>
    211     struct V8ValueTraits {
    212         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 values 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