• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * Copyright (C) 2012 Ericsson AB. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 
32 #ifndef V8Binding_h
33 #define V8Binding_h
34 
35 #include "bindings/v8/DOMWrapperWorld.h"
36 #include "bindings/v8/ExceptionMessages.h"
37 #include "bindings/v8/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 
argumentOrNull(const v8::FunctionCallbackInfo<v8::Value> & info,int index)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>
v8SetReturnValue(const CallbackInfo & info,V v)91 inline void v8SetReturnValue(const CallbackInfo& info, V v)
92 {
93     info.GetReturnValue().Set(v);
94 }
95 
96 template<typename CallbackInfo>
v8SetReturnValueBool(const CallbackInfo & info,bool v)97 inline void v8SetReturnValueBool(const CallbackInfo& info, bool v)
98 {
99     info.GetReturnValue().Set(v);
100 }
101 
102 template<typename CallbackInfo>
v8SetReturnValueInt(const CallbackInfo & info,int v)103 inline void v8SetReturnValueInt(const CallbackInfo& info, int v)
104 {
105     info.GetReturnValue().Set(v);
106 }
107 
108 template<typename CallbackInfo>
v8SetReturnValueUnsigned(const CallbackInfo & info,unsigned v)109 inline void v8SetReturnValueUnsigned(const CallbackInfo& info, unsigned v)
110 {
111     info.GetReturnValue().Set(v);
112 }
113 
114 template<typename CallbackInfo>
v8SetReturnValueNull(const CallbackInfo & info)115 inline void v8SetReturnValueNull(const CallbackInfo& info)
116 {
117     info.GetReturnValue().SetNull();
118 }
119 
120 template<typename CallbackInfo>
v8SetReturnValueUndefined(const CallbackInfo & info)121 inline void v8SetReturnValueUndefined(const CallbackInfo& info)
122 {
123     info.GetReturnValue().SetUndefined();
124 }
125 
126 template<typename CallbackInfo>
v8SetReturnValueEmptyString(const CallbackInfo & info)127 inline void v8SetReturnValueEmptyString(const CallbackInfo& info)
128 {
129     info.GetReturnValue().SetEmptyString();
130 }
131 
132 template <class CallbackInfo>
v8SetReturnValueString(const CallbackInfo & info,const String & string,v8::Isolate * isolate)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>
v8SetReturnValueStringOrNull(const CallbackInfo & info,const String & string,v8::Isolate * isolate)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>
v8SetReturnValueStringOrUndefined(const CallbackInfo & info,const String & string,v8::Isolate * isolate)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.
toCoreString(v8::Handle<v8::String> value)165 inline String toCoreString(v8::Handle<v8::String> value)
166 {
167     return v8StringToWebCoreString<String>(value, Externalize);
168 }
169 
toCoreStringWithNullCheck(v8::Handle<v8::String> value)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 
toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::String> value)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 
toCoreAtomicString(v8::Handle<v8::String> value)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.
toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::Value> value)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.
v8String(v8::Isolate * isolate,const String & string)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 
v8AtomicString(v8::Isolate * isolate,const char * str)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 
v8AtomicString(v8::Isolate * isolate,const char * str,size_t length)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 
v8Undefined()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.
toV8ValueV8ValueTraits232     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 value’s 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