1 /* 2 * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "bindings/v8/V8Binding.h" 33 34 #include "V8Element.h" 35 #include "V8NodeFilter.h" 36 #include "V8Window.h" 37 #include "V8WorkerGlobalScope.h" 38 #include "V8XPathNSResolver.h" 39 #include "bindings/v8/ScriptController.h" 40 #include "bindings/v8/V8NodeFilterCondition.h" 41 #include "bindings/v8/V8ObjectConstructor.h" 42 #include "bindings/v8/V8WindowShell.h" 43 #include "bindings/v8/WorkerScriptController.h" 44 #include "bindings/v8/custom/V8CustomXPathNSResolver.h" 45 #include "core/dom/Element.h" 46 #include "core/dom/NodeFilter.h" 47 #include "core/dom/QualifiedName.h" 48 #include "core/inspector/BindingVisitors.h" 49 #include "core/loader/FrameLoader.h" 50 #include "core/loader/FrameLoaderClient.h" 51 #include "core/frame/Frame.h" 52 #include "core/frame/Settings.h" 53 #include "core/workers/WorkerGlobalScope.h" 54 #include "core/xml/XPathNSResolver.h" 55 #include "gin/public/isolate_holder.h" 56 #include "wtf/ArrayBufferContents.h" 57 #include "wtf/MainThread.h" 58 #include "wtf/MathExtras.h" 59 #include "wtf/StdLibExtras.h" 60 #include "wtf/Threading.h" 61 #include "wtf/text/AtomicString.h" 62 #include "wtf/text/CString.h" 63 #include "wtf/text/StringBuffer.h" 64 #include "wtf/text/StringHash.h" 65 #include "wtf/text/WTFString.h" 66 67 namespace WebCore { 68 69 v8::Handle<v8::Value> setDOMException(int exceptionCode, v8::Isolate* isolate) 70 { 71 // FIXME: pass in an ExceptionState instead for better creationContext. 72 return V8ThrowException::throwDOMException(exceptionCode, v8::Handle<v8::Object>(), isolate); 73 } 74 75 v8::Handle<v8::Value> setDOMException(int exceptionCode, const String& message, v8::Isolate* isolate) 76 { 77 return V8ThrowException::throwDOMException(exceptionCode, message, v8::Handle<v8::Object>(), isolate); 78 } 79 80 v8::Handle<v8::Value> throwError(V8ErrorType errorType, const String& message, v8::Isolate* isolate) 81 { 82 return V8ThrowException::throwError(errorType, message, isolate); 83 } 84 85 v8::Handle<v8::Value> throwError(v8::Handle<v8::Value> exception, v8::Isolate* isolate) 86 { 87 return V8ThrowException::throwError(exception, isolate); 88 } 89 90 v8::Handle<v8::Value> throwUninformativeAndGenericTypeError(v8::Isolate* isolate) 91 { 92 return V8ThrowException::throwTypeError(String(), isolate); 93 } 94 95 v8::Handle<v8::Value> throwTypeError(const String& message, v8::Isolate* isolate) 96 { 97 return V8ThrowException::throwTypeError(message, isolate); 98 } 99 100 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { 101 virtual void* Allocate(size_t size) OVERRIDE 102 { 103 void* data; 104 WTF::ArrayBufferContents::allocateMemory(size, WTF::ArrayBufferContents::ZeroInitialize, data); 105 return data; 106 } 107 108 virtual void* AllocateUninitialized(size_t size) OVERRIDE 109 { 110 void* data; 111 WTF::ArrayBufferContents::allocateMemory(size, WTF::ArrayBufferContents::DontInitialize, data); 112 return data; 113 } 114 115 virtual void Free(void* data, size_t size) OVERRIDE 116 { 117 WTF::ArrayBufferContents::freeMemory(data, size); 118 } 119 }; 120 121 v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator() 122 { 123 DEFINE_STATIC_LOCAL(ArrayBufferAllocator, arrayBufferAllocator, ()); 124 return &arrayBufferAllocator; 125 } 126 127 PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback, v8::Isolate* isolate) 128 { 129 RefPtr<NodeFilter> filter = NodeFilter::create(); 130 131 // FIXME: Should pass in appropriate creationContext 132 v8::Handle<v8::Object> filterWrapper = toV8(filter, v8::Handle<v8::Object>(), isolate).As<v8::Object>(); 133 134 RefPtr<NodeFilterCondition> condition = V8NodeFilterCondition::create(callback, filterWrapper, isolate); 135 filter->setCondition(condition.release()); 136 137 return filter.release(); 138 } 139 140 const int32_t kMaxInt32 = 0x7fffffff; 141 const int32_t kMinInt32 = -kMaxInt32 - 1; 142 const uint32_t kMaxUInt32 = 0xffffffff; 143 const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, maximum integer exactly representable in ECMAScript. 144 145 static double enforceRange(double x, double minimum, double maximum, bool& ok) 146 { 147 if (std::isnan(x) || std::isinf(x)) { 148 ok = false; 149 return 0; 150 } 151 x = trunc(x); 152 if (x < minimum || x > maximum) { 153 ok = false; 154 return 0; 155 } 156 return x; 157 } 158 159 template <typename T> 160 struct IntTypeLimits { 161 }; 162 163 template <> 164 struct IntTypeLimits<int8_t> { 165 static const int8_t minValue = -128; 166 static const int8_t maxValue = 127; 167 static const unsigned numberOfValues = 256; // 2^8 168 }; 169 170 template <> 171 struct IntTypeLimits<uint8_t> { 172 static const uint8_t maxValue = 255; 173 static const unsigned numberOfValues = 256; // 2^8 174 }; 175 176 template <> 177 struct IntTypeLimits<int16_t> { 178 static const short minValue = -32768; 179 static const short maxValue = 32767; 180 static const unsigned numberOfValues = 65536; // 2^16 181 }; 182 183 template <> 184 struct IntTypeLimits<uint16_t> { 185 static const unsigned short maxValue = 65535; 186 static const unsigned numberOfValues = 65536; // 2^16 187 }; 188 189 template <typename T> 190 static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 191 { 192 typedef IntTypeLimits<T> LimitsTrait; 193 ok = true; 194 195 // Fast case. The value is already a 32-bit integer in the right range. 196 if (value->IsInt32()) { 197 int32_t result = value->Int32Value(); 198 if (result >= LimitsTrait::minValue && result <= LimitsTrait::maxValue) 199 return static_cast<T>(result); 200 if (configuration == EnforceRange) { 201 ok = false; 202 return 0; 203 } 204 result %= LimitsTrait::numberOfValues; 205 return static_cast<T>(result > LimitsTrait::maxValue ? result - LimitsTrait::numberOfValues : result); 206 } 207 208 // Can the value be converted to a number? 209 v8::Local<v8::Number> numberObject = value->ToNumber(); 210 if (numberObject.IsEmpty()) { 211 ok = false; 212 return 0; 213 } 214 215 if (configuration == EnforceRange) 216 return enforceRange(numberObject->Value(), LimitsTrait::minValue, LimitsTrait::maxValue, ok); 217 218 double numberValue = numberObject->Value(); 219 if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue) 220 return 0; 221 222 numberValue = numberValue < 0 ? -floor(fabs(numberValue)) : floor(fabs(numberValue)); 223 numberValue = fmod(numberValue, LimitsTrait::numberOfValues); 224 225 return static_cast<T>(numberValue > LimitsTrait::maxValue ? numberValue - LimitsTrait::numberOfValues : numberValue); 226 } 227 228 template <typename T> 229 static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 230 { 231 typedef IntTypeLimits<T> LimitsTrait; 232 ok = true; 233 234 // Fast case. The value is a 32-bit signed integer - possibly positive? 235 if (value->IsInt32()) { 236 int32_t result = value->Int32Value(); 237 if (result >= 0 && result <= LimitsTrait::maxValue) 238 return static_cast<T>(result); 239 if (configuration == EnforceRange) { 240 ok = false; 241 return 0; 242 } 243 return static_cast<T>(result); 244 } 245 246 // Can the value be converted to a number? 247 v8::Local<v8::Number> numberObject = value->ToNumber(); 248 if (numberObject.IsEmpty()) { 249 ok = false; 250 return 0; 251 } 252 253 if (configuration == EnforceRange) 254 return enforceRange(numberObject->Value(), 0, LimitsTrait::maxValue, ok); 255 256 // Does the value convert to nan or to an infinity? 257 double numberValue = numberObject->Value(); 258 if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue) 259 return 0; 260 261 if (configuration == Clamp) 262 return clampTo<T>(numberObject->Value()); 263 264 numberValue = numberValue < 0 ? -floor(fabs(numberValue)) : floor(fabs(numberValue)); 265 return static_cast<T>(fmod(numberValue, LimitsTrait::numberOfValues)); 266 } 267 268 int8_t toInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 269 { 270 return toSmallerInt<int8_t>(value, configuration, ok); 271 } 272 273 uint8_t toUInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 274 { 275 return toSmallerUInt<uint8_t>(value, configuration, ok); 276 } 277 278 int16_t toInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 279 { 280 return toSmallerInt<int16_t>(value, configuration, ok); 281 } 282 283 uint16_t toUInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 284 { 285 return toSmallerUInt<uint16_t>(value, configuration, ok); 286 } 287 288 int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 289 { 290 ok = true; 291 292 // Fast case. The value is already a 32-bit integer. 293 if (value->IsInt32()) 294 return value->Int32Value(); 295 296 // Can the value be converted to a number? 297 ok = false; 298 V8TRYCATCH_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), 0); 299 if (numberObject.IsEmpty()) { 300 return 0; 301 } 302 ok = true; 303 304 if (configuration == EnforceRange) 305 return enforceRange(numberObject->Value(), kMinInt32, kMaxInt32, ok); 306 307 // Does the value convert to nan or to an infinity? 308 double numberValue = numberObject->Value(); 309 if (std::isnan(numberValue) || std::isinf(numberValue)) 310 return 0; 311 312 if (configuration == Clamp) 313 return clampTo<int32_t>(numberObject->Value()); 314 315 V8TRYCATCH_RETURN(int32_t, result, numberObject->Int32Value(), 0); 316 return result; 317 } 318 319 uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 320 { 321 ok = true; 322 323 // Fast case. The value is already a 32-bit unsigned integer. 324 if (value->IsUint32()) 325 return value->Uint32Value(); 326 327 // Fast case. The value is a 32-bit signed integer - possibly positive? 328 if (value->IsInt32()) { 329 int32_t result = value->Int32Value(); 330 if (result >= 0) 331 return result; 332 if (configuration == EnforceRange) { 333 ok = false; 334 return 0; 335 } 336 return result; 337 } 338 339 // Can the value be converted to a number? 340 ok = false; 341 V8TRYCATCH_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), 0); 342 if (numberObject.IsEmpty()) { 343 return 0; 344 } 345 ok = true; 346 347 if (configuration == EnforceRange) 348 return enforceRange(numberObject->Value(), 0, kMaxUInt32, ok); 349 350 // Does the value convert to nan or to an infinity? 351 double numberValue = numberObject->Value(); 352 if (std::isnan(numberValue) || std::isinf(numberValue)) 353 return 0; 354 355 if (configuration == Clamp) 356 return clampTo<uint32_t>(numberObject->Value()); 357 358 V8TRYCATCH_RETURN(uint32_t, result, numberObject->Uint32Value(), 0); 359 return result; 360 } 361 362 int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 363 { 364 ok = true; 365 366 // Fast case. The value is a 32-bit integer. 367 if (value->IsInt32()) 368 return value->Int32Value(); 369 370 // Can the value be converted to a number? 371 v8::Local<v8::Number> numberObject = value->ToNumber(); 372 if (numberObject.IsEmpty()) { 373 ok = false; 374 return 0; 375 } 376 377 double x = numberObject->Value(); 378 379 if (configuration == EnforceRange) 380 return enforceRange(x, -kJSMaxInteger, kJSMaxInteger, ok); 381 382 // Does the value convert to nan or to an infinity? 383 if (std::isnan(x) || std::isinf(x)) 384 return 0; 385 386 // NaNs and +/-Infinity should be 0, otherwise modulo 2^64. 387 unsigned long long integer; 388 doubleToInteger(x, integer); 389 return integer; 390 } 391 392 uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 393 { 394 ok = true; 395 396 // Fast case. The value is a 32-bit unsigned integer. 397 if (value->IsUint32()) 398 return value->Uint32Value(); 399 400 // Fast case. The value is a 32-bit integer. 401 if (value->IsInt32()) { 402 int32_t result = value->Int32Value(); 403 if (result >= 0) 404 return result; 405 if (configuration == EnforceRange) { 406 ok = false; 407 return 0; 408 } 409 return result; 410 } 411 412 // Can the value be converted to a number? 413 v8::Local<v8::Number> numberObject = value->ToNumber(); 414 if (numberObject.IsEmpty()) { 415 ok = false; 416 return 0; 417 } 418 419 double x = numberObject->Value(); 420 421 if (configuration == EnforceRange) 422 return enforceRange(x, 0, kJSMaxInteger, ok); 423 424 // Does the value convert to nan or to an infinity? 425 if (std::isnan(x) || std::isinf(x)) 426 return 0; 427 428 // NaNs and +/-Infinity should be 0, otherwise modulo 2^64. 429 unsigned long long integer; 430 doubleToInteger(x, integer); 431 return integer; 432 } 433 434 v8::Handle<v8::FunctionTemplate> createRawTemplate(v8::Isolate* isolate) 435 { 436 v8::EscapableHandleScope scope(isolate); 437 v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(isolate, V8ObjectConstructor::isValidConstructorMode); 438 return scope.Escape(result); 439 } 440 441 PassRefPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value> value, v8::Isolate* isolate) 442 { 443 RefPtr<XPathNSResolver> resolver; 444 if (V8XPathNSResolver::hasInstance(value, isolate, worldType(isolate))) 445 resolver = V8XPathNSResolver::toNative(v8::Handle<v8::Object>::Cast(value)); 446 else if (value->IsObject()) 447 resolver = V8CustomXPathNSResolver::create(value->ToObject(), isolate); 448 return resolver; 449 } 450 451 v8::Handle<v8::Object> toInnerGlobalObject(v8::Handle<v8::Context> context) 452 { 453 return v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); 454 } 455 456 DOMWindow* toDOMWindow(v8::Handle<v8::Context> context) 457 { 458 v8::Handle<v8::Object> global = context->Global(); 459 ASSERT(!global.IsEmpty()); 460 v8::Handle<v8::Object> window = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), MainWorld)); 461 if (!window.IsEmpty()) 462 return V8Window::toNative(window); 463 window = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), IsolatedWorld)); 464 ASSERT(!window.IsEmpty()); 465 return V8Window::toNative(window); 466 } 467 468 ExecutionContext* toExecutionContext(v8::Handle<v8::Context> context) 469 { 470 v8::Handle<v8::Object> global = context->Global(); 471 v8::Handle<v8::Object> windowWrapper = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), MainWorld)); 472 if (!windowWrapper.IsEmpty()) 473 return V8Window::toNative(windowWrapper)->executionContext(); 474 windowWrapper = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), IsolatedWorld)); 475 if (!windowWrapper.IsEmpty()) 476 return V8Window::toNative(windowWrapper)->executionContext(); 477 v8::Handle<v8::Object> workerWrapper = global->FindInstanceInPrototypeChain(V8WorkerGlobalScope::domTemplate(context->GetIsolate(), WorkerWorld)); 478 if (!workerWrapper.IsEmpty()) 479 return V8WorkerGlobalScope::toNative(workerWrapper)->executionContext(); 480 // FIXME: Is this line of code reachable? 481 return 0; 482 } 483 484 DOMWindow* activeDOMWindow() 485 { 486 v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCallingContext(); 487 if (context.IsEmpty()) { 488 // Unfortunately, when processing script from a plug-in, we might not 489 // have a calling context. In those cases, we fall back to the 490 // entered context. 491 context = v8::Isolate::GetCurrent()->GetEnteredContext(); 492 } 493 return toDOMWindow(context); 494 } 495 496 ExecutionContext* activeExecutionContext() 497 { 498 v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCallingContext(); 499 if (context.IsEmpty()) { 500 // Unfortunately, when processing script from a plug-in, we might not 501 // have a calling context. In those cases, we fall back to the 502 // entered context. 503 context = v8::Isolate::GetCurrent()->GetEnteredContext(); 504 } 505 return toExecutionContext(context); 506 } 507 508 DOMWindow* firstDOMWindow() 509 { 510 return toDOMWindow(v8::Isolate::GetCurrent()->GetEnteredContext()); 511 } 512 513 Document* currentDocument() 514 { 515 return toDOMWindow(v8::Isolate::GetCurrent()->GetCurrentContext())->document(); 516 } 517 518 Frame* toFrameIfNotDetached(v8::Handle<v8::Context> context) 519 { 520 DOMWindow* window = toDOMWindow(context); 521 if (window->isCurrentlyDisplayedInFrame()) 522 return window->frame(); 523 // We return 0 here because |context| is detached from the Frame. If we 524 // did return |frame| we could get in trouble because the frame could be 525 // navigated to another security origin. 526 return 0; 527 } 528 529 v8::Local<v8::Context> toV8Context(ExecutionContext* context, DOMWrapperWorld* world) 530 { 531 if (context->isDocument()) { 532 ASSERT(world); 533 if (Frame* frame = toDocument(context)->frame()) 534 return frame->script().windowShell(world)->context(); 535 } else if (context->isWorkerGlobalScope()) { 536 ASSERT(!world); 537 if (WorkerScriptController* script = toWorkerGlobalScope(context)->script()) 538 return script->context(); 539 } 540 return v8::Local<v8::Context>(); 541 } 542 543 bool handleOutOfMemory() 544 { 545 v8::Local<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext(); 546 547 if (!context->HasOutOfMemoryException()) 548 return false; 549 550 // Warning, error, disable JS for this frame? 551 Frame* frame = toFrameIfNotDetached(context); 552 if (!frame) 553 return true; 554 555 frame->script().clearForOutOfMemory(); 556 frame->loader().client()->didExhaustMemoryAvailableForScript(); 557 558 if (Settings* settings = frame->settings()) 559 settings->setScriptEnabled(false); 560 561 return true; 562 } 563 564 v8::Local<v8::Value> handleMaxRecursionDepthExceeded(v8::Isolate* isolate) 565 { 566 throwError(v8RangeError, "Maximum call stack size exceeded.", isolate); 567 return v8::Local<v8::Value>(); 568 } 569 570 void crashIfV8IsDead() 571 { 572 if (v8::V8::IsDead()) { 573 // FIXME: We temporarily deal with V8 internal error situations 574 // such as out-of-memory by crashing the renderer. 575 CRASH(); 576 } 577 } 578 579 WrapperWorldType worldType(v8::Isolate* isolate) 580 { 581 V8PerIsolateData* data = V8PerIsolateData::from(isolate); 582 if (!data->workerDOMDataStore()) 583 return worldTypeInMainThread(isolate); 584 return WorkerWorld; 585 } 586 587 WrapperWorldType worldTypeInMainThread(v8::Isolate* isolate) 588 { 589 if (!DOMWrapperWorld::isolatedWorldsExist()) 590 return MainWorld; 591 ASSERT(!isolate->GetEnteredContext().IsEmpty()); 592 DOMWrapperWorld* isolatedWorld = DOMWrapperWorld::isolatedWorld(isolate->GetEnteredContext()); 593 if (isolatedWorld) 594 return IsolatedWorld; 595 return MainWorld; 596 } 597 598 DOMWrapperWorld* isolatedWorldForIsolate(v8::Isolate* isolate) 599 { 600 V8PerIsolateData* data = V8PerIsolateData::from(isolate); 601 if (data->workerDOMDataStore()) 602 return 0; 603 if (!DOMWrapperWorld::isolatedWorldsExist()) 604 return 0; 605 ASSERT(isolate->InContext()); 606 return DOMWrapperWorld::isolatedWorld(isolate->GetCurrentContext()); 607 } 608 609 v8::Local<v8::Value> getHiddenValueFromMainWorldWrapper(v8::Isolate* isolate, ScriptWrappable* wrappable, v8::Handle<v8::String> key) 610 { 611 v8::Local<v8::Object> wrapper = wrappable->newLocalWrapper(isolate); 612 return wrapper.IsEmpty() ? v8::Local<v8::Value>() : wrapper->GetHiddenValue(key); 613 } 614 615 static gin::IsolateHolder* mainIsolateHolder = 0; 616 617 v8::Isolate* mainThreadIsolate() 618 { 619 ASSERT(mainIsolateHolder); 620 ASSERT(isMainThread()); 621 return mainIsolateHolder->isolate(); 622 } 623 624 void setMainThreadIsolate(v8::Isolate* isolate) 625 { 626 ASSERT(!mainIsolateHolder || !isolate); 627 ASSERT(isMainThread()); 628 if (isolate) { 629 mainIsolateHolder = new gin::IsolateHolder(isolate); 630 } else { 631 delete mainIsolateHolder; 632 mainIsolateHolder = 0; 633 } 634 } 635 636 v8::Isolate* toIsolate(ExecutionContext* context) 637 { 638 if (context && context->isDocument()) 639 return mainThreadIsolate(); 640 return v8::Isolate::GetCurrent(); 641 } 642 643 v8::Isolate* toIsolate(Frame* frame) 644 { 645 return frame->script().isolate(); 646 } 647 648 } // namespace WebCore 649