Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / core / v8 / V8Binding.h
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 value’s 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