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