Home | History | Annotate | Download | only in v8
      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