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