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/core/v8/DOMWrapperWorld.h"
     36 #include "bindings/core/v8/ExceptionMessages.h"
     37 #include "bindings/core/v8/ExceptionState.h"
     38 #include "bindings/core/v8/ScriptValue.h"
     39 #include "bindings/core/v8/ScriptWrappable.h"
     40 #include "bindings/core/v8/V8BindingMacros.h"
     41 #include "bindings/core/v8/V8PerIsolateData.h"
     42 #include "bindings/core/v8/V8StringResource.h"
     43 #include "bindings/core/v8/V8ThrowException.h"
     44 #include "bindings/core/v8/V8ValueCache.h"
     45 #include "platform/heap/Heap.h"
     46 #include "wtf/GetPtr.h"
     47 #include "wtf/MathExtras.h"
     48 #include "wtf/text/AtomicString.h"
     49 #include <v8.h>
     50 
     51 namespace blink {
     52 
     53 class LocalDOMWindow;
     54 class Document;
     55 class EventListener;
     56 class ExecutionContext;
     57 class ExceptionState;
     58 class LocalFrame;
     59 class NodeFilter;
     60 class XPathNSResolver;
     61 
     62 namespace TraceEvent {
     63 class ConvertableToTraceFormat;
     64 }
     65 
     66 const int kMaxRecursionDepth = 22;
     67 
     68 // Helpers for throwing JavaScript TypeErrors for arity mismatches.
     69 void setArityTypeError(ExceptionState&, const char* valid, unsigned provided);
     70 v8::Local<v8::Value> createMinimumArityTypeErrorForMethod(const char* method, const char* type, unsigned expected, unsigned provided, v8::Isolate*);
     71 v8::Local<v8::Value> createMinimumArityTypeErrorForConstructor(const char* type, unsigned expected, unsigned provided, v8::Isolate*);
     72 void setMinimumArityTypeError(ExceptionState&, unsigned expected, unsigned provided);
     73 
     74 v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator();
     75 
     76 template<typename CallbackInfo, typename V>
     77 inline void v8SetReturnValue(const CallbackInfo& info, V v)
     78 {
     79     info.GetReturnValue().Set(v);
     80 }
     81 
     82 template<typename CallbackInfo>
     83 inline void v8SetReturnValueBool(const CallbackInfo& info, bool v)
     84 {
     85     info.GetReturnValue().Set(v);
     86 }
     87 
     88 template<typename CallbackInfo>
     89 inline void v8SetReturnValueInt(const CallbackInfo& info, int v)
     90 {
     91     info.GetReturnValue().Set(v);
     92 }
     93 
     94 template<typename CallbackInfo>
     95 inline void v8SetReturnValueUnsigned(const CallbackInfo& info, unsigned v)
     96 {
     97     info.GetReturnValue().Set(v);
     98 }
     99 
    100 template<typename CallbackInfo>
    101 inline void v8SetReturnValueNull(const CallbackInfo& info)
    102 {
    103     info.GetReturnValue().SetNull();
    104 }
    105 
    106 template<typename CallbackInfo>
    107 inline void v8SetReturnValueUndefined(const CallbackInfo& info)
    108 {
    109     info.GetReturnValue().SetUndefined();
    110 }
    111 
    112 template<typename CallbackInfo>
    113 inline void v8SetReturnValueEmptyString(const CallbackInfo& info)
    114 {
    115     info.GetReturnValue().SetEmptyString();
    116 }
    117 
    118 template <class CallbackInfo>
    119 inline void v8SetReturnValueString(const CallbackInfo& info, const String& string, v8::Isolate* isolate)
    120 {
    121     if (string.isNull()) {
    122         v8SetReturnValueEmptyString(info);
    123         return;
    124     }
    125     V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl());
    126 }
    127 
    128 template <class CallbackInfo>
    129 inline void v8SetReturnValueStringOrNull(const CallbackInfo& info, const String& string, v8::Isolate* isolate)
    130 {
    131     if (string.isNull()) {
    132         v8SetReturnValueNull(info);
    133         return;
    134     }
    135     V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl());
    136 }
    137 
    138 template <class CallbackInfo>
    139 inline void v8SetReturnValueStringOrUndefined(const CallbackInfo& info, const String& string, v8::Isolate* isolate)
    140 {
    141     if (string.isNull()) {
    142         v8SetReturnValueUndefined(info);
    143         return;
    144     }
    145     V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl());
    146 }
    147 
    148 // Convert v8::String to a WTF::String. If the V8 string is not already
    149 // an external string then it is transformed into an external string at this
    150 // point to avoid repeated conversions.
    151 inline String toCoreString(v8::Handle<v8::String> value)
    152 {
    153     return v8StringToWebCoreString<String>(value, Externalize);
    154 }
    155 
    156 inline String toCoreStringWithNullCheck(v8::Handle<v8::String> value)
    157 {
    158     if (value.IsEmpty() || value->IsNull())
    159         return String();
    160     return toCoreString(value);
    161 }
    162 
    163 inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::String> value)
    164 {
    165     if (value.IsEmpty() || value->IsNull() || value->IsUndefined())
    166         return String();
    167     return toCoreString(value);
    168 }
    169 
    170 inline AtomicString toCoreAtomicString(v8::Handle<v8::String> value)
    171 {
    172     return v8StringToWebCoreString<AtomicString>(value, Externalize);
    173 }
    174 
    175 // This method will return a null String if the v8::Value does not contain a v8::String.
    176 // It will not call ToString() on the v8::Value. If you want ToString() to be called,
    177 // please use the TONATIVE_FOR_V8STRINGRESOURCE_*() macros instead.
    178 inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::Value> value)
    179 {
    180     if (value.IsEmpty() || !value->IsString())
    181         return String();
    182     return toCoreString(value.As<v8::String>());
    183 }
    184 
    185 // Convert a string to a V8 string.
    186 // Return a V8 external string that shares the underlying buffer with the given
    187 // WebCore string. The reference counting mechanism is used to keep the
    188 // underlying buffer alive while the string is still live in the V8 engine.
    189 inline v8::Handle<v8::String> v8String(v8::Isolate* isolate, const String& string)
    190 {
    191     if (string.isNull())
    192         return v8::String::Empty(isolate);
    193     return V8PerIsolateData::from(isolate)->stringCache()->v8ExternalString(string.impl(), isolate);
    194 }
    195 
    196 inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str)
    197 {
    198     ASSERT(isolate);
    199     return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, strlen(str));
    200 }
    201 
    202 inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str, size_t length)
    203 {
    204     ASSERT(isolate);
    205     return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, length);
    206 }
    207 
    208 inline v8::Handle<v8::Value> v8Undefined()
    209 {
    210     return v8::Handle<v8::Value>();
    211 }
    212 
    213 // Converts a DOM object to a v8 value. This function is intended to be used
    214 // internally. If you want to convert a DOM object to a V8 value,
    215 //  - Use toV8 if you can include V8X.h.
    216 //  - Use V8ValueTraits<T>::toV8Value if you cannot include V8X.h.
    217 // Note: Including bindings/{core, modules}/v8/V8*.h from core and modules
    218 // is fine. In such a case, perhaps toV8 is what you want.
    219 // Note: toV8NoInline is a non-inline toV8 and V8ValueTraits::toV8Value offers
    220 // more: You can handle value conversion generally with it.
    221 template<typename T>
    222 v8::Handle<v8::Value> toV8NoInline(T* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*);
    223 
    224 template <typename T>
    225 struct V8ValueTraits {
    226     static v8::Handle<v8::Value> toV8Value(const T& value, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    227     {
    228         if (!WTF::getPtr(value))
    229             return v8::Null(isolate);
    230         return toV8NoInline(WTF::getPtr(value), creationContext, isolate);
    231     }
    232 };
    233 
    234 template<>
    235 struct V8ValueTraits<String> {
    236     static inline v8::Handle<v8::Value> toV8Value(const String& value, v8::Handle<v8::Object>, v8::Isolate* isolate)
    237     {
    238         return v8String(isolate, value);
    239     }
    240 };
    241 
    242 template<>
    243 struct V8ValueTraits<AtomicString> {
    244     static inline v8::Handle<v8::Value> toV8Value(const AtomicString& value, v8::Handle<v8::Object>, v8::Isolate* isolate)
    245     {
    246         return v8String(isolate, value);
    247     }
    248 };
    249 
    250 template<size_t n>
    251 struct V8ValueTraits<char[n]> {
    252     static inline v8::Handle<v8::Value> toV8Value(char const (&value)[n], v8::Handle<v8::Object>, v8::Isolate* isolate)
    253     {
    254         return v8String(isolate, value);
    255     }
    256 };
    257 
    258 template<size_t n>
    259 struct V8ValueTraits<char const[n]> {
    260     static inline v8::Handle<v8::Value> toV8Value(char const (&value)[n], v8::Handle<v8::Object>, v8::Isolate* isolate)
    261     {
    262         return v8String(isolate, value);
    263     }
    264 };
    265 
    266 template<>
    267 struct V8ValueTraits<const char*> {
    268     static inline v8::Handle<v8::Value> toV8Value(const char* const& value, v8::Handle<v8::Object>, v8::Isolate* isolate)
    269     {
    270         if (!value) {
    271             // We return an empty string, not null, in order to align
    272             // with v8String(isolate, String()).
    273             return v8::String::Empty(isolate);
    274         }
    275         return v8String(isolate, value);
    276     }
    277 };
    278 
    279 template<>
    280 struct V8ValueTraits<char*> {
    281     static inline v8::Handle<v8::Value> toV8Value(char* const& value, v8::Handle<v8::Object> object, v8::Isolate* isolate)
    282     {
    283         return V8ValueTraits<const char*>::toV8Value(value, object, isolate);
    284     }
    285 };
    286 
    287 template<>
    288 struct V8ValueTraits<int> {
    289     static inline v8::Handle<v8::Value> toV8Value(const int& value, v8::Handle<v8::Object>, v8::Isolate* isolate)
    290     {
    291         return v8::Integer::New(isolate, value);
    292     }
    293 };
    294 
    295 template<>
    296 struct V8ValueTraits<long> {
    297     static inline v8::Handle<v8::Value> toV8Value(const long& value, v8::Handle<v8::Object>, v8::Isolate* isolate)
    298     {
    299         return v8::Integer::New(isolate, value);
    300     }
    301 };
    302 
    303 template<>
    304 struct V8ValueTraits<unsigned> {
    305     static inline v8::Handle<v8::Value> toV8Value(const unsigned& value, v8::Handle<v8::Object>, v8::Isolate* isolate)
    306     {
    307         return v8::Integer::NewFromUnsigned(isolate, value);
    308     }
    309 };
    310 
    311 template<>
    312 struct V8ValueTraits<unsigned long> {
    313     static inline v8::Handle<v8::Value> toV8Value(const unsigned long& value, v8::Handle<v8::Object>, v8::Isolate* isolate)
    314     {
    315         return v8::Integer::NewFromUnsigned(isolate, value);
    316     }
    317 };
    318 
    319 template<>
    320 struct V8ValueTraits<float> {
    321     static inline v8::Handle<v8::Value> toV8Value(const float& value, v8::Handle<v8::Object>, v8::Isolate* isolate)
    322     {
    323         return v8::Number::New(isolate, value);
    324     }
    325 };
    326 
    327 template<>
    328 struct V8ValueTraits<double> {
    329     static inline v8::Handle<v8::Value> toV8Value(const double& value, v8::Handle<v8::Object>, v8::Isolate* isolate)
    330     {
    331         return v8::Number::New(isolate, value);
    332     }
    333 };
    334 
    335 template<>
    336 struct V8ValueTraits<bool> {
    337     static inline v8::Handle<v8::Value> toV8Value(const bool& value, v8::Handle<v8::Object>, v8::Isolate* isolate)
    338     {
    339         return v8::Boolean::New(isolate, value);
    340     }
    341 };
    342 
    343 // V8NullType and V8UndefinedType are used only for the value conversion.
    344 class V8NullType { };
    345 class V8UndefinedType { };
    346 
    347 template<>
    348 struct V8ValueTraits<V8NullType> {
    349     static inline v8::Handle<v8::Value> toV8Value(const V8NullType&, v8::Handle<v8::Object>, v8::Isolate* isolate)
    350     {
    351         return v8::Null(isolate);
    352     }
    353 };
    354 
    355 template<>
    356 struct V8ValueTraits<V8UndefinedType> {
    357     static inline v8::Handle<v8::Value> toV8Value(const V8UndefinedType&, v8::Handle<v8::Object>, v8::Isolate* isolate)
    358     {
    359         return v8::Undefined(isolate);
    360     }
    361 };
    362 
    363 template<>
    364 struct V8ValueTraits<ScriptValue> {
    365     static inline v8::Handle<v8::Value> toV8Value(const ScriptValue& value, v8::Handle<v8::Object>, v8::Isolate*)
    366     {
    367         return value.v8Value();
    368     }
    369 };
    370 
    371 template<>
    372 struct V8ValueTraits<v8::Handle<v8::Value> > {
    373     static inline v8::Handle<v8::Value> toV8Value(const v8::Handle<v8::Value>& value, v8::Handle<v8::Object>, v8::Isolate*)
    374     {
    375         return value;
    376     }
    377 };
    378 
    379 template<>
    380 struct V8ValueTraits<v8::Local<v8::Value> > {
    381     static inline v8::Handle<v8::Value> toV8Value(const v8::Local<v8::Value>& value, v8::Handle<v8::Object>, v8::Isolate*)
    382     {
    383         return value;
    384     }
    385 };
    386 
    387 template<typename T, size_t inlineCapacity>
    388 v8::Handle<v8::Value> v8Array(const Vector<T, inlineCapacity>& iterator, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    389 {
    390     v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size());
    391     int index = 0;
    392     typename Vector<T, inlineCapacity>::const_iterator end = iterator.end();
    393     typedef V8ValueTraits<T> TraitsType;
    394     for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter)
    395         result->Set(v8::Integer::New(isolate, index++), TraitsType::toV8Value(*iter, creationContext, isolate));
    396     return result;
    397 }
    398 
    399 template <typename T, size_t inlineCapacity, typename Allocator>
    400 struct V8ValueTraits<WTF::Vector<T, inlineCapacity, Allocator> > {
    401     static v8::Handle<v8::Value> toV8Value(const Vector<T, inlineCapacity, Allocator>& value, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    402     {
    403         return v8Array(value, creationContext, isolate);
    404     }
    405 };
    406 
    407 template<typename T, size_t inlineCapacity>
    408 v8::Handle<v8::Value> v8Array(const HeapVector<T, inlineCapacity>& iterator, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    409 {
    410     v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size());
    411     int index = 0;
    412     typename HeapVector<T, inlineCapacity>::const_iterator end = iterator.end();
    413     typedef V8ValueTraits<T> TraitsType;
    414     for (typename HeapVector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter)
    415         result->Set(v8::Integer::New(isolate, index++), TraitsType::toV8Value(*iter, creationContext, isolate));
    416     return result;
    417 }
    418 
    419 template <typename T, size_t inlineCapacity>
    420 struct V8ValueTraits<HeapVector<T, inlineCapacity> > {
    421     static v8::Handle<v8::Value> toV8Value(const HeapVector<T, inlineCapacity>& value, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
    422     {
    423         return v8Array(value, creationContext, isolate);
    424     }
    425 };
    426 
    427 // Conversion flags, used in toIntXX/toUIntXX.
    428 enum IntegerConversionConfiguration {
    429     NormalConversion,
    430     EnforceRange,
    431     Clamp
    432 };
    433 
    434 // Convert a value to a 8-bit signed integer. The conversion fails if the
    435 // value cannot be converted to a number or the range violated per WebIDL:
    436 // http://www.w3.org/TR/WebIDL/#es-byte
    437 int8_t toInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&);
    438 inline int8_t toInt8(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
    439 {
    440     return toInt8(value, NormalConversion, exceptionState);
    441 }
    442 
    443 // Convert a value to a 8-bit integer assuming the conversion cannot fail.
    444 int8_t toInt8(v8::Handle<v8::Value>);
    445 
    446 // Convert a value to a 8-bit unsigned integer. The conversion fails if the
    447 // value cannot be converted to a number or the range violated per WebIDL:
    448 // http://www.w3.org/TR/WebIDL/#es-octet
    449 uint8_t toUInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&);
    450 inline uint8_t toUInt8(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
    451 {
    452     return toUInt8(value, NormalConversion, exceptionState);
    453 }
    454 
    455 // Convert a value to a 8-bit unsigned integer assuming the conversion cannot fail.
    456 uint8_t toUInt8(v8::Handle<v8::Value>);
    457 
    458 // Convert a value to a 16-bit signed integer. The conversion fails if the
    459 // value cannot be converted to a number or the range violated per WebIDL:
    460 // http://www.w3.org/TR/WebIDL/#es-short
    461 int16_t toInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&);
    462 inline int16_t toInt16(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
    463 {
    464     return toInt16(value, NormalConversion, exceptionState);
    465 }
    466 
    467 // Convert a value to a 16-bit integer assuming the conversion cannot fail.
    468 int16_t toInt16(v8::Handle<v8::Value>);
    469 
    470 // Convert a value to a 16-bit unsigned integer. The conversion fails if the
    471 // value cannot be converted to a number or the range violated per WebIDL:
    472 // http://www.w3.org/TR/WebIDL/#es-unsigned-short
    473 uint16_t toUInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&);
    474 inline uint16_t toUInt16(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
    475 {
    476     return toUInt16(value, NormalConversion, exceptionState);
    477 }
    478 
    479 // Convert a value to a 16-bit unsigned integer assuming the conversion cannot fail.
    480 uint16_t toUInt16(v8::Handle<v8::Value>);
    481 
    482 // Convert a value to a 32-bit signed integer. The conversion fails if the
    483 // value cannot be converted to a number or the range violated per WebIDL:
    484 // http://www.w3.org/TR/WebIDL/#es-long
    485 int32_t toInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&);
    486 inline int32_t toInt32(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
    487 {
    488     return toInt32(value, NormalConversion, exceptionState);
    489 }
    490 
    491 // Convert a value to a 32-bit integer assuming the conversion cannot fail.
    492 int32_t toInt32(v8::Handle<v8::Value>);
    493 
    494 // Convert a value to a 32-bit unsigned integer. The conversion fails if the
    495 // value cannot be converted to a number or the range violated per WebIDL:
    496 // http://www.w3.org/TR/WebIDL/#es-unsigned-long
    497 uint32_t toUInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&);
    498 inline uint32_t toUInt32(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
    499 {
    500     return toUInt32(value, NormalConversion, exceptionState);
    501 }
    502 
    503 // Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail.
    504 uint32_t toUInt32(v8::Handle<v8::Value>);
    505 
    506 // Convert a value to a 64-bit signed integer. The conversion fails if the
    507 // value cannot be converted to a number or the range violated per WebIDL:
    508 // http://www.w3.org/TR/WebIDL/#es-long-long
    509 int64_t toInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&);
    510 inline int64_t toInt64(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
    511 {
    512     return toInt64(value, NormalConversion, exceptionState);
    513 }
    514 
    515 // Convert a value to a 64-bit integer assuming the conversion cannot fail.
    516 int64_t toInt64(v8::Handle<v8::Value>);
    517 
    518 // Convert a value to a 64-bit unsigned integer. The conversion fails if the
    519 // value cannot be converted to a number or the range violated per WebIDL:
    520 // http://www.w3.org/TR/WebIDL/#es-unsigned-long-long
    521 uint64_t toUInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&);
    522 inline uint64_t toUInt64(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
    523 {
    524     return toUInt64(value, NormalConversion, exceptionState);
    525 }
    526 
    527 // Convert a value to a 64-bit unsigned integer assuming the conversion cannot fail.
    528 uint64_t toUInt64(v8::Handle<v8::Value>);
    529 
    530 // Convert a value to a single precision float, which might fail.
    531 float toFloat(v8::Handle<v8::Value>, ExceptionState&);
    532 
    533 // Convert a value to a single precision float assuming the conversion cannot fail.
    534 inline float toFloat(v8::Local<v8::Value> value)
    535 {
    536     return static_cast<float>(value->NumberValue());
    537 }
    538 
    539 // Convert a value to a double precision float, which might fail.
    540 double toDouble(v8::Handle<v8::Value>, ExceptionState&);
    541 
    542 // Converts a value to a String, throwing if any code unit is outside 0-255.
    543 String toByteString(v8::Handle<v8::Value>, ExceptionState&);
    544 
    545 // Converts a value to a String, replacing unmatched UTF-16 surrogates with replacement characters.
    546 String toScalarValueString(v8::Handle<v8::Value>, ExceptionState&);
    547 
    548 inline v8::Handle<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate)
    549 {
    550     return value ? v8::True(isolate) : v8::False(isolate);
    551 }
    552 
    553 inline double toCoreDate(v8::Handle<v8::Value> object)
    554 {
    555     if (object->IsDate())
    556         return v8::Handle<v8::Date>::Cast(object)->ValueOf();
    557     if (object->IsNumber())
    558         return object->NumberValue();
    559     return std::numeric_limits<double>::quiet_NaN();
    560 }
    561 
    562 inline v8::Handle<v8::Value> v8DateOrNaN(double value, v8::Isolate* isolate)
    563 {
    564     ASSERT(isolate);
    565     return v8::Date::New(isolate, std::isfinite(value) ? value : std::numeric_limits<double>::quiet_NaN());
    566 }
    567 
    568 // FIXME: Remove the special casing for NodeFilter and XPathNSResolver.
    569 PassRefPtrWillBeRawPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value>, v8::Handle<v8::Object>, ScriptState*);
    570 PassRefPtrWillBeRawPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value>, v8::Isolate*);
    571 
    572 template<class T> struct NativeValueTraits;
    573 
    574 bool toV8Sequence(v8::Handle<v8::Value>, uint32_t& length, v8::Isolate*, ExceptionState&);
    575 
    576 // Converts a JavaScript value to an array as per the Web IDL specification:
    577 // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array
    578 template <class T, class V8T>
    579 Vector<RefPtr<T> > toRefPtrNativeArrayUnchecked(v8::Local<v8::Value> v8Value, uint32_t length, v8::Isolate* isolate, ExceptionState& exceptionState)
    580 {
    581     Vector<RefPtr<T> > result;
    582     result.reserveInitialCapacity(length);
    583     v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value);
    584     v8::TryCatch block;
    585     for (uint32_t i = 0; i < length; ++i) {
    586         v8::Handle<v8::Value> element = object->Get(i);
    587         if (block.HasCaught()) {
    588             exceptionState.rethrowV8Exception(block.Exception());
    589             return Vector<RefPtr<T> >();
    590         }
    591         if (V8T::hasInstance(element, isolate)) {
    592             v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element);
    593             result.uncheckedAppend(V8T::toImpl(elementObject));
    594         } else {
    595             exceptionState.throwTypeError("Invalid Array element type");
    596             return Vector<RefPtr<T> >();
    597         }
    598     }
    599     return result;
    600 }
    601 
    602 template <class T, class V8T>
    603 Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, ExceptionState& exceptionState)
    604 {
    605     v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value));
    606     uint32_t length = 0;
    607     if (value->IsArray()) {
    608         length = v8::Local<v8::Array>::Cast(v8Value)->Length();
    609     } else if (!toV8Sequence(value, length, isolate, exceptionState)) {
    610         if (!exceptionState.hadException())
    611             exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex));
    612         return Vector<RefPtr<T> >();
    613     }
    614     return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, exceptionState);
    615 }
    616 
    617 template <class T, class V8T>
    618 Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, const String& propertyName, v8::Isolate* isolate, ExceptionState& exceptionState)
    619 {
    620     v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value));
    621     uint32_t length = 0;
    622     if (value->IsArray()) {
    623         length = v8::Local<v8::Array>::Cast(v8Value)->Length();
    624     } else if (!toV8Sequence(value, length, isolate, exceptionState)) {
    625         if (!exceptionState.hadException())
    626             exceptionState.throwTypeError(ExceptionMessages::notASequenceTypeProperty(propertyName));
    627         return Vector<RefPtr<T> >();
    628     }
    629     return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, exceptionState);
    630 }
    631 
    632 template <class T, class V8T>
    633 WillBeHeapVector<RefPtrWillBeMember<T> > toRefPtrWillBeMemberNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, ExceptionState& exceptionState)
    634 {
    635     v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value));
    636     uint32_t length = 0;
    637     if (value->IsArray()) {
    638         length = v8::Local<v8::Array>::Cast(v8Value)->Length();
    639     } else if (!toV8Sequence(value, length, isolate, exceptionState)) {
    640         if (!exceptionState.hadException())
    641             exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex));
    642         return WillBeHeapVector<RefPtrWillBeMember<T> >();
    643     }
    644 
    645     WillBeHeapVector<RefPtrWillBeMember<T> > result;
    646     result.reserveInitialCapacity(length);
    647     v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value);
    648     v8::TryCatch block;
    649     for (uint32_t i = 0; i < length; ++i) {
    650         v8::Handle<v8::Value> element = object->Get(i);
    651         if (block.HasCaught()) {
    652             exceptionState.rethrowV8Exception(block.Exception());
    653             return WillBeHeapVector<RefPtrWillBeMember<T> >();
    654         }
    655         if (V8T::hasInstance(element, isolate)) {
    656             v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element);
    657             result.uncheckedAppend(V8T::toImpl(elementObject));
    658         } else {
    659             exceptionState.throwTypeError("Invalid Array element type");
    660             return WillBeHeapVector<RefPtrWillBeMember<T> >();
    661         }
    662     }
    663     return result;
    664 }
    665 
    666 template <class T, class V8T>
    667 WillBeHeapVector<RefPtrWillBeMember<T> > toRefPtrWillBeMemberNativeArray(v8::Handle<v8::Value> value, const String& propertyName, v8::Isolate* isolate, ExceptionState& exceptionState)
    668 {
    669     v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value));
    670     uint32_t length = 0;
    671     if (value->IsArray()) {
    672         length = v8::Local<v8::Array>::Cast(v8Value)->Length();
    673     } else if (!toV8Sequence(value, length, isolate, exceptionState)) {
    674         if (!exceptionState.hadException())
    675             exceptionState.throwTypeError(ExceptionMessages::notASequenceTypeProperty(propertyName));
    676         return WillBeHeapVector<RefPtrWillBeMember<T> >();
    677     }
    678 
    679     WillBeHeapVector<RefPtrWillBeMember<T> > result;
    680     result.reserveInitialCapacity(length);
    681     v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value);
    682     v8::TryCatch block;
    683     for (uint32_t i = 0; i < length; ++i) {
    684         v8::Handle<v8::Value> element = object->Get(i);
    685         if (block.HasCaught()) {
    686             exceptionState.rethrowV8Exception(block.Exception());
    687             return WillBeHeapVector<RefPtrWillBeMember<T> >();
    688         }
    689         if (V8T::hasInstance(element, isolate)) {
    690             v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element);
    691             result.uncheckedAppend(V8T::toImpl(elementObject));
    692         } else {
    693             exceptionState.throwTypeError("Invalid Array element type");
    694             return WillBeHeapVector<RefPtrWillBeMember<T> >();
    695         }
    696     }
    697     return result;
    698 }
    699 
    700 template <class T, class V8T>
    701 HeapVector<Member<T> > toMemberNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, ExceptionState& exceptionState)
    702 {
    703     v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value));
    704     uint32_t length = 0;
    705     if (value->IsArray()) {
    706         length = v8::Local<v8::Array>::Cast(v8Value)->Length();
    707     } else if (!toV8Sequence(value, length, isolate, exceptionState)) {
    708         if (!exceptionState.hadException())
    709             exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex));
    710         return HeapVector<Member<T> >();
    711     }
    712 
    713     HeapVector<Member<T> > result;
    714     result.reserveInitialCapacity(length);
    715     v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value);
    716     v8::TryCatch block;
    717     for (uint32_t i = 0; i < length; ++i) {
    718         v8::Handle<v8::Value> element = object->Get(i);
    719         if (UNLIKELY(block.HasCaught())) {
    720             exceptionState.rethrowV8Exception(block.Exception());
    721             return HeapVector<Member<T> >();
    722         }
    723         if (V8T::hasInstance(element, isolate)) {
    724             v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element);
    725             result.uncheckedAppend(V8T::toImpl(elementObject));
    726         } else {
    727             exceptionState.throwTypeError("Invalid Array element type");
    728             return HeapVector<Member<T> >();
    729         }
    730     }
    731     return result;
    732 }
    733 
    734 // Converts a JavaScript value to an array as per the Web IDL specification:
    735 // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array
    736 template <class T>
    737 Vector<T> toImplArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, ExceptionState& exceptionState)
    738 {
    739     v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value));
    740     uint32_t length = 0;
    741     if (value->IsArray()) {
    742         length = v8::Local<v8::Array>::Cast(v8Value)->Length();
    743     } else if (!toV8Sequence(value, length, isolate, exceptionState)) {
    744         if (!exceptionState.hadException())
    745             exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex));
    746         return Vector<T>();
    747     }
    748 
    749     Vector<T> result;
    750     result.reserveInitialCapacity(length);
    751     typedef NativeValueTraits<T> TraitsType;
    752     v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value);
    753     v8::TryCatch block;
    754     for (uint32_t i = 0; i < length; ++i) {
    755         v8::Handle<v8::Value> element = object->Get(i);
    756         if (UNLIKELY(block.HasCaught())) {
    757             exceptionState.rethrowV8Exception(block.Exception());
    758             return Vector<T>();
    759         }
    760         result.uncheckedAppend(TraitsType::nativeValue(element, isolate, exceptionState));
    761         if (exceptionState.hadException())
    762             return Vector<T>();
    763     }
    764     return result;
    765 }
    766 
    767 template <class T>
    768 Vector<T> toImplArguments(const v8::FunctionCallbackInfo<v8::Value>& info, int startIndex, ExceptionState& exceptionState)
    769 {
    770     ASSERT(startIndex <= info.Length());
    771     Vector<T> result;
    772     typedef NativeValueTraits<T> TraitsType;
    773     int length = info.Length();
    774     result.reserveInitialCapacity(length);
    775     for (int i = startIndex; i < length; ++i) {
    776         result.uncheckedAppend(TraitsType::nativeValue(info[i], info.GetIsolate(), exceptionState));
    777         if (exceptionState.hadException())
    778             return Vector<T>();
    779     }
    780     return result;
    781 }
    782 
    783 // Validates that the passed object is a sequence type per WebIDL spec
    784 // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-sequence
    785 inline bool toV8Sequence(v8::Handle<v8::Value> value, uint32_t& length, v8::Isolate* isolate, ExceptionState& exceptionState)
    786 {
    787     // Attempt converting to a sequence if the value is not already an array but is
    788     // any kind of object except for a native Date object or a native RegExp object.
    789     ASSERT(!value->IsArray());
    790     // FIXME: Do we really need to special case Date and RegExp object?
    791     // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22806
    792     if (!value->IsObject() || value->IsDate() || value->IsRegExp()) {
    793         // The caller is responsible for reporting a TypeError.
    794         return false;
    795     }
    796 
    797     v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value));
    798     v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value);
    799     v8::Local<v8::String> lengthSymbol = v8AtomicString(isolate, "length");
    800 
    801     // FIXME: The specification states that the length property should be used as fallback, if value
    802     // is not a platform object that supports indexed properties. If it supports indexed properties,
    803     // length should actually be one greater than values maximum indexed property index.
    804     v8::TryCatch block;
    805     v8::Local<v8::Value> lengthValue = object->Get(lengthSymbol);
    806     if (block.HasCaught()) {
    807         exceptionState.rethrowV8Exception(block.Exception());
    808         return false;
    809     }
    810 
    811     if (lengthValue->IsUndefined() || lengthValue->IsNull()) {
    812         // The caller is responsible for reporting a TypeError.
    813         return false;
    814     }
    815 
    816     uint32_t sequenceLength = lengthValue->Int32Value();
    817     if (block.HasCaught()) {
    818         exceptionState.rethrowV8Exception(block.Exception());
    819         return false;
    820     }
    821 
    822     length = sequenceLength;
    823     return true;
    824 }
    825 
    826 template<>
    827 struct NativeValueTraits<String> {
    828     static inline String nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate, ExceptionState& exceptionState)
    829     {
    830         V8StringResource<> stringValue(value);
    831         if (!stringValue.prepare(exceptionState))
    832             return String();
    833         return stringValue;
    834     }
    835 };
    836 
    837 template<>
    838 struct NativeValueTraits<int> {
    839     static inline int nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate, ExceptionState& exceptionState)
    840     {
    841         return toInt32(value, exceptionState);
    842     }
    843 };
    844 
    845 template<>
    846 struct NativeValueTraits<unsigned> {
    847     static inline unsigned nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate, ExceptionState& exceptionState)
    848     {
    849         return toUInt32(value, exceptionState);
    850     }
    851 };
    852 
    853 template<>
    854 struct NativeValueTraits<float> {
    855     static inline float nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate, ExceptionState& exceptionState)
    856     {
    857         return toFloat(value, exceptionState);
    858     }
    859 };
    860 
    861 template<>
    862 struct NativeValueTraits<double> {
    863     static inline double nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate, ExceptionState& exceptionState)
    864     {
    865         return toDouble(value, exceptionState);
    866     }
    867 };
    868 
    869 template<>
    870 struct NativeValueTraits<v8::Handle<v8::Value> > {
    871     static inline v8::Handle<v8::Value> nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate, ExceptionState&)
    872     {
    873         return value;
    874     }
    875 };
    876 
    877 template<>
    878 struct NativeValueTraits<ScriptValue> {
    879     static inline ScriptValue nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate, ExceptionState&)
    880     {
    881         return ScriptValue(ScriptState::current(isolate), value);
    882     }
    883 };
    884 
    885 template <typename T>
    886 struct NativeValueTraits<Vector<T> > {
    887     static inline Vector<T> nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate, ExceptionState& exceptionState)
    888     {
    889         return toImplArray<T>(value, 0, isolate, exceptionState);
    890     }
    891 };
    892 
    893 v8::Isolate* toIsolate(ExecutionContext*);
    894 v8::Isolate* toIsolate(LocalFrame*);
    895 
    896 LocalDOMWindow* toDOMWindow(v8::Handle<v8::Value>, v8::Isolate*);
    897 LocalDOMWindow* toDOMWindow(v8::Handle<v8::Context>);
    898 LocalDOMWindow* enteredDOMWindow(v8::Isolate*);
    899 LocalDOMWindow* currentDOMWindow(v8::Isolate*);
    900 LocalDOMWindow* callingDOMWindow(v8::Isolate*);
    901 ExecutionContext* toExecutionContext(v8::Handle<v8::Context>);
    902 ExecutionContext* currentExecutionContext(v8::Isolate*);
    903 ExecutionContext* callingExecutionContext(v8::Isolate*);
    904 
    905 // Returns a V8 context associated with a ExecutionContext and a DOMWrapperWorld.
    906 // This method returns an empty context if there is no frame or the frame is already detached.
    907 v8::Local<v8::Context> toV8Context(ExecutionContext*, DOMWrapperWorld&);
    908 // Returns a V8 context associated with a LocalFrame and a DOMWrapperWorld.
    909 // This method returns an empty context if the frame is already detached.
    910 v8::Local<v8::Context> toV8Context(LocalFrame*, DOMWrapperWorld&);
    911 
    912 // Returns the frame object of the window object associated with
    913 // a context, if the window is currently being displayed in the LocalFrame.
    914 LocalFrame* toFrameIfNotDetached(v8::Handle<v8::Context>);
    915 
    916 // If the current context causes out of memory, JavaScript setting
    917 // is disabled and it returns true.
    918 bool handleOutOfMemory();
    919 void crashIfV8IsDead();
    920 
    921 inline bool isUndefinedOrNull(v8::Handle<v8::Value> value)
    922 {
    923     return value->IsNull() || value->IsUndefined();
    924 }
    925 v8::Handle<v8::Function> getBoundFunction(v8::Handle<v8::Function>);
    926 
    927 // Attaches |environment| to |function| and returns it.
    928 inline v8::Local<v8::Function> createClosure(v8::FunctionCallback function, v8::Handle<v8::Value> environment, v8::Isolate* isolate)
    929 {
    930     return v8::Function::New(isolate, function, environment);
    931 }
    932 
    933 // FIXME: This will be soon embedded in the generated code.
    934 template<class Collection> static void indexedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
    935 {
    936     Collection* collection = toScriptWrappableBase(info.Holder())->toImpl<Collection>();
    937     int length = collection->length();
    938     v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), length);
    939     for (int i = 0; i < length; ++i) {
    940         // FIXME: Do we need to check that the item function returns a non-null value for this index?
    941         v8::Handle<v8::Integer> integer = v8::Integer::New(info.GetIsolate(), i);
    942         properties->Set(integer, integer);
    943     }
    944     v8SetReturnValue(info, properties);
    945 }
    946 
    947 // These methods store hidden values into an array that is stored in the internal field of a DOM wrapper.
    948 void addHiddenValueToArray(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex, v8::Isolate*);
    949 void removeHiddenValueFromArray(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex, v8::Isolate*);
    950 void moveEventListenerToNewWrapper(v8::Handle<v8::Object>, EventListener* oldValue, v8::Local<v8::Value> newValue, int cacheIndex, v8::Isolate*);
    951 
    952 PassRefPtr<JSONValue> v8ToJSONValue(v8::Isolate*, v8::Handle<v8::Value>, int);
    953 
    954 // Result values for platform object 'deleter' methods,
    955 // http://www.w3.org/TR/WebIDL/#delete
    956 enum DeleteResult {
    957     DeleteSuccess,
    958     DeleteReject,
    959     DeleteUnknownProperty
    960 };
    961 
    962 class V8IsolateInterruptor : public ThreadState::Interruptor {
    963 public:
    964     explicit V8IsolateInterruptor(v8::Isolate* isolate) : m_isolate(isolate) { }
    965 
    966     static void onInterruptCallback(v8::Isolate* isolate, void* data)
    967     {
    968         reinterpret_cast<V8IsolateInterruptor*>(data)->onInterrupted();
    969     }
    970 
    971     virtual void requestInterrupt() OVERRIDE
    972     {
    973         m_isolate->RequestInterrupt(&onInterruptCallback, this);
    974     }
    975 
    976     virtual void clearInterrupt() OVERRIDE
    977     {
    978         m_isolate->ClearInterrupt();
    979     }
    980 
    981 private:
    982     v8::Isolate* m_isolate;
    983 };
    984 
    985 class V8TestingScope {
    986 public:
    987     explicit V8TestingScope(v8::Isolate*);
    988     ScriptState* scriptState() const;
    989     v8::Isolate* isolate() const;
    990     ~V8TestingScope();
    991 
    992 private:
    993     v8::HandleScope m_handleScope;
    994     v8::Context::Scope m_contextScope;
    995     RefPtr<ScriptState> m_scriptState;
    996 };
    997 
    998 void GetDevToolsFunctionInfo(v8::Handle<v8::Function>, v8::Isolate*, int& scriptId, String& resourceName, int& lineNumber);
    999 PassRefPtr<TraceEvent::ConvertableToTraceFormat> devToolsTraceEventData(ExecutionContext*, v8::Handle<v8::Function>, v8::Isolate*);
   1000 
   1001 class V8RethrowTryCatchScope FINAL {
   1002 public:
   1003     explicit V8RethrowTryCatchScope(v8::TryCatch& block) : m_block(block) { }
   1004     ~V8RethrowTryCatchScope()
   1005     {
   1006         // ReThrow() is a no-op if no exception has been caught, so always call.
   1007         m_block.ReThrow();
   1008     }
   1009 
   1010 private:
   1011     v8::TryCatch& m_block;
   1012 };
   1013 
   1014 // Returns an object representing {done: true, value: undefined}.
   1015 v8::Local<v8::Value> v8DoneIteratorResult(v8::Isolate*);
   1016 
   1017 // Returns an object representing {done: false, value: |value|}.
   1018 v8::Local<v8::Value> v8IteratorResult(v8::Isolate*, v8::Handle<v8::Value>);
   1019 template <typename T>
   1020 v8::Local<v8::Value> v8IteratorResult(ScriptState* scriptState, const T& value)
   1021 {
   1022     return v8IteratorResult(scriptState->isolate(), V8ValueTraits<T>::toV8Value(value, scriptState->context()->Global(), scriptState->isolate()));
   1023 }
   1024 
   1025 } // namespace blink
   1026 
   1027 #endif // V8Binding_h
   1028