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