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/V8BindingMacros.h" 38 #include "bindings/v8/V8PerIsolateData.h" 39 #include "bindings/v8/V8StringResource.h" 40 #include "bindings/v8/V8ThrowException.h" 41 #include "bindings/v8/V8ValueCache.h" 42 #include "wtf/MathExtras.h" 43 #include "wtf/text/AtomicString.h" 44 #include <v8.h> 45 46 namespace WebCore { 47 48 class DOMWindow; 49 class Document; 50 class Frame; 51 class NodeFilter; 52 class ExecutionContext; 53 class ScriptWrappable; 54 class XPathNSResolver; 55 56 const int kMaxRecursionDepth = 22; 57 58 // Schedule a DOM exception to be thrown, if the exception code is different 59 // from zero. 60 v8::Handle<v8::Value> setDOMException(int, v8::Isolate*); 61 v8::Handle<v8::Value> setDOMException(int, const String&, v8::Isolate*); 62 63 // Schedule a JavaScript error to be thrown. 64 v8::Handle<v8::Value> throwError(V8ErrorType, const String&, v8::Isolate*); 65 66 // Schedule a JavaScript error to be thrown. 67 v8::Handle<v8::Value> throwError(v8::Handle<v8::Value>, v8::Isolate*); 68 69 // A helper for throwing JavaScript TypeError. 70 v8::Handle<v8::Value> throwTypeError(const String&, v8::Isolate*); 71 72 // FIXME: Remove this once we kill its callers. 73 v8::Handle<v8::Value> throwUninformativeAndGenericTypeError(v8::Isolate*); 74 75 v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator(); 76 77 v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value>, uint32_t& length, v8::Isolate*); 78 79 inline v8::Handle<v8::Value> argumentOrNull(const v8::FunctionCallbackInfo<v8::Value>& info, int index) 80 { 81 return index >= info.Length() ? v8::Local<v8::Value>() : info[index]; 82 } 83 84 template<typename CallbackInfo, typename V> 85 inline void v8SetReturnValue(const CallbackInfo& info, V v) 86 { 87 info.GetReturnValue().Set(v); 88 } 89 90 template<typename CallbackInfo> 91 inline void v8SetReturnValueBool(const CallbackInfo& info, bool v) 92 { 93 info.GetReturnValue().Set(v); 94 } 95 96 template<typename CallbackInfo> 97 inline void v8SetReturnValueInt(const CallbackInfo& info, int v) 98 { 99 info.GetReturnValue().Set(v); 100 } 101 102 template<typename CallbackInfo> 103 inline void v8SetReturnValueUnsigned(const CallbackInfo& info, unsigned v) 104 { 105 info.GetReturnValue().Set(v); 106 } 107 108 template<typename CallbackInfo> 109 inline void v8SetReturnValueNull(const CallbackInfo& info) 110 { 111 info.GetReturnValue().SetNull(); 112 } 113 114 template<typename CallbackInfo> 115 inline void v8SetReturnValueUndefined(const CallbackInfo& info) 116 { 117 info.GetReturnValue().SetUndefined(); 118 } 119 120 template<typename CallbackInfo> 121 inline void v8SetReturnValueEmptyString(const CallbackInfo& info) 122 { 123 info.GetReturnValue().SetEmptyString(); 124 } 125 126 template <class CallbackInfo> 127 inline void v8SetReturnValueString(const CallbackInfo& info, const String& string, v8::Isolate* isolate) 128 { 129 if (string.isNull()) { 130 v8SetReturnValueEmptyString(info); 131 return; 132 } 133 V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); 134 } 135 136 template <class CallbackInfo> 137 inline void v8SetReturnValueStringOrNull(const CallbackInfo& info, const String& string, v8::Isolate* isolate) 138 { 139 if (string.isNull()) { 140 v8SetReturnValueNull(info); 141 return; 142 } 143 V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); 144 } 145 146 template <class CallbackInfo> 147 inline void v8SetReturnValueStringOrUndefined(const CallbackInfo& info, const String& string, v8::Isolate* isolate) 148 { 149 if (string.isNull()) { 150 v8SetReturnValueUndefined(info); 151 return; 152 } 153 V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); 154 } 155 156 // Convert v8::String to a WTF::String. If the V8 string is not already 157 // an external string then it is transformed into an external string at this 158 // point to avoid repeated conversions. 159 inline String toCoreString(v8::Handle<v8::String> value) 160 { 161 return v8StringToWebCoreString<String>(value, Externalize); 162 } 163 164 inline String toCoreStringWithNullCheck(v8::Handle<v8::String> value) 165 { 166 if (value.IsEmpty() || value->IsNull()) 167 return String(); 168 return toCoreString(value); 169 } 170 171 inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::String> value) 172 { 173 if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) 174 return String(); 175 return toCoreString(value); 176 } 177 178 inline AtomicString toCoreAtomicString(v8::Handle<v8::String> value) 179 { 180 return v8StringToWebCoreString<AtomicString>(value, Externalize); 181 } 182 183 // This method will return a null String if the v8::Value does not contain a v8::String. 184 // It will not call ToString() on the v8::Value. If you want ToString() to be called, 185 // please use the V8TRYCATCH_FOR_V8STRINGRESOURCE_*() macros instead. 186 inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::Value> value) 187 { 188 if (value.IsEmpty() || !value->IsString()) 189 return String(); 190 191 return toCoreString(value.As<v8::String>()); 192 } 193 194 // Convert a string to a V8 string. 195 // Return a V8 external string that shares the underlying buffer with the given 196 // WebCore string. The reference counting mechanism is used to keep the 197 // underlying buffer alive while the string is still live in the V8 engine. 198 inline v8::Handle<v8::String> v8String(v8::Isolate* isolate, const String& string) 199 { 200 if (string.isNull()) 201 return v8::String::Empty(isolate); 202 return V8PerIsolateData::from(isolate)->stringCache()->v8ExternalString(string.impl(), isolate); 203 } 204 205 inline v8::Handle<v8::Value> v8Undefined() 206 { 207 return v8::Handle<v8::Value>(); 208 } 209 210 template <class T> 211 struct V8ValueTraits { 212 static inline v8::Handle<v8::Value> arrayV8Value(const T& value, v8::Isolate* isolate) 213 { 214 return toV8(WTF::getPtr(value), v8::Handle<v8::Object>(), isolate); 215 } 216 }; 217 218 template<> 219 struct V8ValueTraits<String> { 220 static inline v8::Handle<v8::Value> arrayV8Value(const String& value, v8::Isolate* isolate) 221 { 222 return v8String(isolate, value); 223 } 224 }; 225 226 template<> 227 struct V8ValueTraits<unsigned> { 228 static inline v8::Handle<v8::Value> arrayV8Value(const unsigned& value, v8::Isolate* isolate) 229 { 230 return v8::Integer::NewFromUnsigned(value, isolate); 231 } 232 }; 233 234 template<> 235 struct V8ValueTraits<unsigned long> { 236 static inline v8::Handle<v8::Value> arrayV8Value(const unsigned long& value, v8::Isolate* isolate) 237 { 238 return v8::Integer::NewFromUnsigned(value, isolate); 239 } 240 }; 241 242 template<> 243 struct V8ValueTraits<float> { 244 static inline v8::Handle<v8::Value> arrayV8Value(const float& value, v8::Isolate* isolate) 245 { 246 return v8::Number::New(isolate, value); 247 } 248 }; 249 250 template<> 251 struct V8ValueTraits<double> { 252 static inline v8::Handle<v8::Value> arrayV8Value(const double& value, v8::Isolate* isolate) 253 { 254 return v8::Number::New(isolate, value); 255 } 256 }; 257 258 template<typename T, size_t inlineCapacity> 259 v8::Handle<v8::Value> v8Array(const Vector<T, inlineCapacity>& iterator, v8::Isolate* isolate) 260 { 261 v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size()); 262 int index = 0; 263 typename Vector<T, inlineCapacity>::const_iterator end = iterator.end(); 264 typedef V8ValueTraits<T> TraitsType; 265 for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) 266 result->Set(v8::Integer::New(index++, isolate), TraitsType::arrayV8Value(*iter, isolate)); 267 return result; 268 } 269 270 // Conversion flags, used in toIntXX/toUIntXX. 271 enum IntegerConversionConfiguration { 272 NormalConversion, 273 EnforceRange, 274 Clamp 275 }; 276 277 // Convert a value to a 8-bit signed integer. The conversion fails if the 278 // value cannot be converted to a number or the range violated per WebIDL: 279 // http://www.w3.org/TR/WebIDL/#es-byte 280 int8_t toInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); 281 inline int8_t toInt8(v8::Handle<v8::Value> value, bool& ok) { return toInt8(value, NormalConversion, ok); } 282 283 // Convert a value to a 8-bit integer assuming the conversion cannot fail. 284 inline int8_t toInt8(v8::Handle<v8::Value> value) 285 { 286 bool ok; 287 return toInt8(value, NormalConversion, ok); 288 } 289 290 // Convert a value to a 8-bit unsigned integer. The conversion fails if the 291 // value cannot be converted to a number or the range violated per WebIDL: 292 // http://www.w3.org/TR/WebIDL/#es-octet 293 uint8_t toUInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); 294 inline uint8_t toUInt8(v8::Handle<v8::Value> value, bool& ok) { return toUInt8(value, NormalConversion, ok); } 295 296 // Convert a value to a 8-bit unsigned integer assuming the conversion cannot fail. 297 inline uint8_t toUInt8(v8::Handle<v8::Value> value) 298 { 299 bool ok; 300 return toUInt8(value, NormalConversion, ok); 301 } 302 303 // Convert a value to a 16-bit signed integer. The conversion fails if the 304 // value cannot be converted to a number or the range violated per WebIDL: 305 // http://www.w3.org/TR/WebIDL/#es-short 306 int16_t toInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); 307 inline int16_t toInt16(v8::Handle<v8::Value> value, bool& ok) { return toInt16(value, NormalConversion, ok); } 308 309 // Convert a value to a 16-bit integer assuming the conversion cannot fail. 310 inline int16_t toInt16(v8::Handle<v8::Value> value) 311 { 312 bool ok; 313 return toInt16(value, NormalConversion, ok); 314 } 315 316 // Convert a value to a 16-bit unsigned integer. The conversion fails if the 317 // value cannot be converted to a number or the range violated per WebIDL: 318 // http://www.w3.org/TR/WebIDL/#es-unsigned-short 319 uint16_t toUInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); 320 inline uint16_t toUInt16(v8::Handle<v8::Value> value, bool& ok) { return toUInt16(value, NormalConversion, ok); } 321 322 // Convert a value to a 16-bit unsigned integer assuming the conversion cannot fail. 323 inline uint16_t toUInt16(v8::Handle<v8::Value> value) 324 { 325 bool ok; 326 return toUInt16(value, NormalConversion, ok); 327 } 328 329 // Convert a value to a 32-bit signed integer. The conversion fails if the 330 // value cannot be converted to a number or the range violated per WebIDL: 331 // http://www.w3.org/TR/WebIDL/#es-long 332 int32_t toInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); 333 inline int32_t toInt32(v8::Handle<v8::Value> value, bool& ok) { return toInt32(value, NormalConversion, ok); } 334 335 // Convert a value to a 32-bit integer assuming the conversion cannot fail. 336 inline int32_t toInt32(v8::Handle<v8::Value> value) 337 { 338 bool ok; 339 return toInt32(value, NormalConversion, ok); 340 } 341 342 // Convert a value to a 32-bit unsigned integer. The conversion fails if the 343 // value cannot be converted to a number or the range violated per WebIDL: 344 // http://www.w3.org/TR/WebIDL/#es-unsigned-long 345 uint32_t toUInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); 346 inline uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok) { return toUInt32(value, NormalConversion, ok); } 347 348 // Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail. 349 inline uint32_t toUInt32(v8::Handle<v8::Value> value) 350 { 351 bool ok; 352 return toUInt32(value, NormalConversion, ok); 353 } 354 355 // Convert a value to a 64-bit signed integer. The conversion fails if the 356 // value cannot be converted to a number or the range violated per WebIDL: 357 // http://www.w3.org/TR/WebIDL/#es-long-long 358 int64_t toInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); 359 360 // Convert a value to a 64-bit integer assuming the conversion cannot fail. 361 inline int64_t toInt64(v8::Handle<v8::Value> value) 362 { 363 bool ok; 364 return toInt64(value, NormalConversion, ok); 365 } 366 367 // Convert a value to a 64-bit unsigned integer. The conversion fails if the 368 // value cannot be converted to a number or the range violated per WebIDL: 369 // http://www.w3.org/TR/WebIDL/#es-unsigned-long-long 370 uint64_t toUInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); 371 372 // Convert a value to a 64-bit unsigned integer assuming the conversion cannot fail. 373 inline uint64_t toUInt64(v8::Handle<v8::Value> value) 374 { 375 bool ok; 376 return toUInt64(value, NormalConversion, ok); 377 } 378 379 inline float toFloat(v8::Local<v8::Value> value) 380 { 381 return static_cast<float>(value->NumberValue()); 382 } 383 384 WrapperWorldType worldType(v8::Isolate*); 385 WrapperWorldType worldTypeInMainThread(v8::Isolate*); 386 387 DOMWrapperWorld* isolatedWorldForIsolate(v8::Isolate*); 388 389 template<class T> struct NativeValueTraits; 390 391 template<> 392 struct NativeValueTraits<String> { 393 static inline String nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) 394 { 395 V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, value, String()); 396 return stringValue; 397 } 398 }; 399 400 template<> 401 struct NativeValueTraits<unsigned> { 402 static inline unsigned nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) 403 { 404 return toUInt32(value); 405 } 406 }; 407 408 template<> 409 struct NativeValueTraits<float> { 410 static inline float nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) 411 { 412 return static_cast<float>(value->NumberValue()); 413 } 414 }; 415 416 template<> 417 struct NativeValueTraits<double> { 418 static inline double nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) 419 { 420 return static_cast<double>(value->NumberValue()); 421 } 422 }; 423 424 template<> 425 struct NativeValueTraits<v8::Handle<v8::Value> > { 426 static inline v8::Handle<v8::Value> nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) 427 { 428 return value; 429 } 430 }; 431 432 // Converts a JavaScript value to an array as per the Web IDL specification: 433 // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array 434 template <class T, class V8T> 435 Vector<RefPtr<T> > toRefPtrNativeArrayUnchecked(v8::Local<v8::Value> v8Value, uint32_t length, v8::Isolate* isolate, bool* success = 0) 436 { 437 Vector<RefPtr<T> > result; 438 result.reserveInitialCapacity(length); 439 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); 440 for (uint32_t i = 0; i < length; ++i) { 441 v8::Handle<v8::Value> element = object->Get(i); 442 443 if (V8T::hasInstance(element, isolate, worldType(isolate))) { 444 v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element); 445 result.uncheckedAppend(V8T::toNative(elementObject)); 446 } else { 447 if (success) 448 *success = false; 449 throwTypeError("Invalid Array element type", isolate); 450 return Vector<RefPtr<T> >(); 451 } 452 } 453 return result; 454 } 455 456 template <class T, class V8T> 457 Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, bool* success = 0) 458 { 459 if (success) 460 *success = true; 461 462 v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); 463 uint32_t length = 0; 464 if (value->IsArray()) { 465 length = v8::Local<v8::Array>::Cast(v8Value)->Length(); 466 } else if (toV8Sequence(value, length, isolate).IsEmpty()) { 467 throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); 468 return Vector<RefPtr<T> >(); 469 } 470 471 return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success); 472 } 473 474 template <class T, class V8T> 475 Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, const String& propertyName, v8::Isolate* isolate, bool* success = 0) 476 { 477 if (success) 478 *success = true; 479 480 v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); 481 uint32_t length = 0; 482 if (value->IsArray()) { 483 length = v8::Local<v8::Array>::Cast(v8Value)->Length(); 484 } else if (toV8Sequence(value, length, isolate).IsEmpty()) { 485 throwTypeError(ExceptionMessages::notASequenceTypeProperty(propertyName), isolate); 486 return Vector<RefPtr<T> >(); 487 } 488 489 return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success); 490 } 491 492 // Converts a JavaScript value to an array as per the Web IDL specification: 493 // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array 494 template <class T> 495 Vector<T> toNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate) 496 { 497 v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); 498 uint32_t length = 0; 499 if (value->IsArray()) { 500 length = v8::Local<v8::Array>::Cast(v8Value)->Length(); 501 } else if (toV8Sequence(value, length, isolate).IsEmpty()) { 502 throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); 503 return Vector<T>(); 504 } 505 506 Vector<T> result; 507 result.reserveInitialCapacity(length); 508 typedef NativeValueTraits<T> TraitsType; 509 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); 510 for (uint32_t i = 0; i < length; ++i) 511 result.uncheckedAppend(TraitsType::nativeValue(object->Get(i), isolate)); 512 return result; 513 } 514 515 template <class T> 516 Vector<T> toNativeArguments(const v8::FunctionCallbackInfo<v8::Value>& info, int startIndex) 517 { 518 ASSERT(startIndex <= info.Length()); 519 Vector<T> result; 520 typedef NativeValueTraits<T> TraitsType; 521 int length = info.Length(); 522 result.reserveInitialCapacity(length); 523 for (int i = startIndex; i < length; ++i) 524 result.uncheckedAppend(TraitsType::nativeValue(info[i], info.GetIsolate())); 525 return result; 526 } 527 528 // Validates that the passed object is a sequence type per WebIDL spec 529 // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-sequence 530 inline v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value> value, uint32_t& length, v8::Isolate* isolate) 531 { 532 // Attempt converting to a sequence if the value is not already an array but is 533 // any kind of object except for a native Date object or a native RegExp object. 534 ASSERT(!value->IsArray()); 535 // FIXME: Do we really need to special case Date and RegExp object? 536 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22806 537 if (!value->IsObject() || value->IsDate() || value->IsRegExp()) { 538 // The caller is responsible for reporting a TypeError. 539 return v8Undefined(); 540 } 541 542 v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); 543 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); 544 v8::Local<v8::String> lengthSymbol = v8::String::NewFromUtf8(isolate, "length", v8::String::kInternalizedString, 6); 545 546 // FIXME: The specification states that the length property should be used as fallback, if value 547 // is not a platform object that supports indexed properties. If it supports indexed properties, 548 // length should actually be one greater than values maximum indexed property index. 549 V8TRYCATCH(v8::Local<v8::Value>, lengthValue, object->Get(lengthSymbol)); 550 551 if (lengthValue->IsUndefined() || lengthValue->IsNull()) { 552 // The caller is responsible for reporting a TypeError. 553 return v8Undefined(); 554 } 555 556 V8TRYCATCH(uint32_t, sequenceLength, lengthValue->Int32Value()); 557 length = sequenceLength; 558 559 return v8Value; 560 } 561 562 PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value>, v8::Isolate*); 563 564 inline bool isUndefinedOrNull(v8::Handle<v8::Value> value) 565 { 566 return value->IsNull() || value->IsUndefined(); 567 } 568 569 // Returns true if the provided object is to be considered a 'host object', as used in the 570 // HTML5 structured clone algorithm. 571 inline bool isHostObject(v8::Handle<v8::Object> object) 572 { 573 // If the object has any internal fields, then we won't be able to serialize or deserialize 574 // them; conveniently, this is also a quick way to detect DOM wrapper objects, because 575 // the mechanism for these relies on data stored in these fields. We should 576 // catch external array data as a special case. 577 return object->InternalFieldCount() || object->HasIndexedPropertiesInExternalArrayData(); 578 } 579 580 inline v8::Handle<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) 581 { 582 return value ? v8::True(isolate) : v8::False(isolate); 583 } 584 585 // Since v8Boolean(value, isolate) crashes if we pass a null isolate, 586 // we need to use v8BooleanWithCheck(value, isolate) if an isolate can be null. 587 // 588 // FIXME: Remove all null isolates from V8 bindings, and remove v8BooleanWithCheck(value, isolate). 589 inline v8::Handle<v8::Boolean> v8BooleanWithCheck(bool value, v8::Isolate* isolate) 590 { 591 return isolate ? v8Boolean(value, isolate) : v8Boolean(value, v8::Isolate::GetCurrent()); 592 } 593 594 inline double toWebCoreDate(v8::Handle<v8::Value> object) 595 { 596 if (object->IsDate()) 597 return v8::Handle<v8::Date>::Cast(object)->ValueOf(); 598 if (object->IsNumber()) 599 return object->NumberValue(); 600 return std::numeric_limits<double>::quiet_NaN(); 601 } 602 603 inline v8::Handle<v8::Value> v8DateOrNull(double value, v8::Isolate* isolate) 604 { 605 ASSERT(isolate); 606 return std::isfinite(value) ? v8::Date::New(isolate, value) : v8::Handle<v8::Value>::Cast(v8::Null(isolate)); 607 } 608 609 inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str) 610 { 611 ASSERT(isolate); 612 return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, strlen(str)); 613 } 614 615 inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str, size_t length) 616 { 617 ASSERT(isolate); 618 return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, length); 619 } 620 621 622 v8::Handle<v8::FunctionTemplate> createRawTemplate(v8::Isolate*); 623 624 PassRefPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value>, v8::Isolate*); 625 626 v8::Handle<v8::Object> toInnerGlobalObject(v8::Handle<v8::Context>); 627 DOMWindow* toDOMWindow(v8::Handle<v8::Context>); 628 ExecutionContext* toExecutionContext(v8::Handle<v8::Context>); 629 630 DOMWindow* activeDOMWindow(); 631 ExecutionContext* activeExecutionContext(); 632 DOMWindow* firstDOMWindow(); 633 Document* currentDocument(); 634 635 // Returns the context associated with a ExecutionContext. 636 v8::Local<v8::Context> toV8Context(ExecutionContext*, DOMWrapperWorld*); 637 638 // Returns the frame object of the window object associated with 639 // a context, if the window is currently being displayed in the Frame. 640 Frame* toFrameIfNotDetached(v8::Handle<v8::Context>); 641 642 inline DOMWrapperWorld* isolatedWorldForEnteredContext(v8::Isolate* isolate) 643 { 644 v8::Handle<v8::Context> context = isolate->GetEnteredContext(); 645 if (context.IsEmpty()) 646 return 0; 647 return DOMWrapperWorld::isolatedWorld(context); 648 } 649 650 // FIXME: This will be soon embedded in the generated code. 651 template<class Collection> static void indexedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) 652 { 653 Collection* collection = reinterpret_cast<Collection*>(info.Holder()->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); 654 int length = collection->length(); 655 v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), length); 656 for (int i = 0; i < length; ++i) { 657 // FIXME: Do we need to check that the item function returns a non-null value for this index? 658 v8::Handle<v8::Integer> integer = v8::Integer::New(i, info.GetIsolate()); 659 properties->Set(integer, integer); 660 } 661 v8SetReturnValue(info, properties); 662 } 663 664 // If the current context causes out of memory, JavaScript setting 665 // is disabled and it returns true. 666 bool handleOutOfMemory(); 667 v8::Local<v8::Value> handleMaxRecursionDepthExceeded(v8::Isolate*); 668 669 void crashIfV8IsDead(); 670 671 template <class T> 672 v8::Handle<T> unsafeHandleFromRawValue(const T* value) 673 { 674 const v8::Handle<T>* handle = reinterpret_cast<const v8::Handle<T>*>(&value); 675 return *handle; 676 } 677 678 // Attaches |environment| to |function| and returns it. 679 inline v8::Local<v8::Function> createClosure(v8::FunctionCallback function, v8::Handle<v8::Value> environment, v8::Isolate* isolate) 680 { 681 return v8::Function::New(isolate, function, environment); 682 } 683 684 v8::Local<v8::Value> getHiddenValueFromMainWorldWrapper(v8::Isolate*, ScriptWrappable*, v8::Handle<v8::String> key); 685 686 v8::Isolate* mainThreadIsolate(); 687 v8::Isolate* toIsolate(ExecutionContext*); 688 v8::Isolate* toIsolate(Frame*); 689 690 // Can only be called by blink::initialize 691 void setMainThreadIsolate(v8::Isolate*); 692 693 // Converts a DOM object to a v8 value. 694 // This is a no-inline version of toV8(). If you want to call toV8() 695 // without creating #include cycles, you can use this function instead. 696 // Each specialized implementation will be generated. 697 template<typename T> 698 v8::Handle<v8::Value> toV8NoInline(T* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*); 699 } // namespace WebCore 700 701 #endif // V8Binding_h 702