Upstream version 5.34.98.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / v8 / V8Binding.cpp
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/V8BindingMacros.h"
41 #include "bindings/v8/V8NodeFilterCondition.h"
42 #include "bindings/v8/V8ObjectConstructor.h"
43 #include "bindings/v8/V8WindowShell.h"
44 #include "bindings/v8/WorkerScriptController.h"
45 #include "bindings/v8/custom/V8CustomXPathNSResolver.h"
46 #include "core/dom/Element.h"
47 #include "core/dom/NodeFilter.h"
48 #include "core/dom/QualifiedName.h"
49 #include "core/inspector/BindingVisitors.h"
50 #include "core/loader/FrameLoader.h"
51 #include "core/loader/FrameLoaderClient.h"
52 #include "core/frame/Frame.h"
53 #include "core/frame/Settings.h"
54 #include "core/workers/WorkerGlobalScope.h"
55 #include "core/xml/XPathNSResolver.h"
56 #include "gin/public/isolate_holder.h"
57 #include "wtf/ArrayBufferContents.h"
58 #include "wtf/MainThread.h"
59 #include "wtf/MathExtras.h"
60 #include "wtf/StdLibExtras.h"
61 #include "wtf/Threading.h"
62 #include "wtf/text/AtomicString.h"
63 #include "wtf/text/CString.h"
64 #include "wtf/text/StringBuffer.h"
65 #include "wtf/text/StringHash.h"
66 #include "wtf/text/WTFString.h"
67
68 namespace WebCore {
69
70 v8::Handle<v8::Value> setDOMException(int exceptionCode, v8::Isolate* isolate)
71 {
72     // FIXME: pass in an ExceptionState instead for better creationContext.
73     return V8ThrowException::throwDOMException(exceptionCode, v8::Handle<v8::Object>(), isolate);
74 }
75
76 v8::Handle<v8::Value> setDOMException(int exceptionCode, const String& message, v8::Isolate* isolate)
77 {
78     return V8ThrowException::throwDOMException(exceptionCode, message, v8::Handle<v8::Object>(), isolate);
79 }
80
81 v8::Handle<v8::Value> throwError(V8ErrorType errorType, const String& message, v8::Isolate* isolate)
82 {
83     return V8ThrowException::throwError(errorType, message, isolate);
84 }
85
86 v8::Handle<v8::Value> throwError(v8::Handle<v8::Value> exception, v8::Isolate* isolate)
87 {
88     return V8ThrowException::throwError(exception, isolate);
89 }
90
91 v8::Handle<v8::Value> throwTypeError(const String& message, v8::Isolate* isolate)
92 {
93     return V8ThrowException::throwTypeError(message, isolate);
94 }
95
96 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
97     virtual void* Allocate(size_t size) OVERRIDE
98     {
99         void* data;
100         WTF::ArrayBufferContents::allocateMemory(size, WTF::ArrayBufferContents::ZeroInitialize, data);
101         return data;
102     }
103
104     virtual void* AllocateUninitialized(size_t size) OVERRIDE
105     {
106         void* data;
107         WTF::ArrayBufferContents::allocateMemory(size, WTF::ArrayBufferContents::DontInitialize, data);
108         return data;
109     }
110
111     virtual void Free(void* data, size_t size) OVERRIDE
112     {
113         WTF::ArrayBufferContents::freeMemory(data, size);
114     }
115 };
116
117 v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator()
118 {
119     DEFINE_STATIC_LOCAL(ArrayBufferAllocator, arrayBufferAllocator, ());
120     return &arrayBufferAllocator;
121 }
122
123 PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback, v8::Isolate* isolate)
124 {
125     RefPtr<NodeFilter> filter = NodeFilter::create();
126
127     // FIXME: Should pass in appropriate creationContext
128     v8::Handle<v8::Object> filterWrapper = toV8(filter, v8::Handle<v8::Object>(), isolate).As<v8::Object>();
129
130     RefPtr<NodeFilterCondition> condition = V8NodeFilterCondition::create(callback, filterWrapper, isolate);
131     filter->setCondition(condition.release());
132
133     return filter.release();
134 }
135
136 DOMWindow* toNativeDOMWindow(v8::Handle<v8::Value> value, v8::Isolate* isolate)
137 {
138     if (value.IsEmpty() || !value->IsObject())
139         return 0;
140
141     v8::Handle<v8::Object> global = v8::Handle<v8::Object>::Cast(value);
142     v8::Handle<v8::Object> windowWrapper = global->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldType(isolate)));
143     if (windowWrapper.IsEmpty())
144         return 0;
145     return V8Window::toNative(windowWrapper);
146 }
147
148 const int32_t kMaxInt32 = 0x7fffffff;
149 const int32_t kMinInt32 = -kMaxInt32 - 1;
150 const uint32_t kMaxUInt32 = 0xffffffff;
151 const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, maximum uniquely representable integer in ECMAScript.
152
153 static double enforceRange(double x, double minimum, double maximum, const char* typeName, ExceptionState& exceptionState)
154 {
155     if (std::isnan(x) || std::isinf(x)) {
156         exceptionState.throwTypeError("Value is" + String(std::isinf(x) ? " infinite and" : "") + " not of type '" + String(typeName) + "'.");
157         return 0;
158     }
159     x = trunc(x);
160     if (x < minimum || x > maximum) {
161         exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range.");
162         return 0;
163     }
164     return x;
165 }
166
167 template <typename T>
168 struct IntTypeLimits {
169 };
170
171 template <>
172 struct IntTypeLimits<int8_t> {
173     static const int8_t minValue = -128;
174     static const int8_t maxValue = 127;
175     static const unsigned numberOfValues = 256; // 2^8
176 };
177
178 template <>
179 struct IntTypeLimits<uint8_t> {
180     static const uint8_t maxValue = 255;
181     static const unsigned numberOfValues = 256; // 2^8
182 };
183
184 template <>
185 struct IntTypeLimits<int16_t> {
186     static const short minValue = -32768;
187     static const short maxValue = 32767;
188     static const unsigned numberOfValues = 65536; // 2^16
189 };
190
191 template <>
192 struct IntTypeLimits<uint16_t> {
193     static const unsigned short maxValue = 65535;
194     static const unsigned numberOfValues = 65536; // 2^16
195 };
196
197 template <typename T>
198 static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, const char* typeName, ExceptionState& exceptionState)
199 {
200     typedef IntTypeLimits<T> LimitsTrait;
201
202     // Fast case. The value is already a 32-bit integer in the right range.
203     if (value->IsInt32()) {
204         int32_t result = value->Int32Value();
205         if (result >= LimitsTrait::minValue && result <= LimitsTrait::maxValue)
206             return static_cast<T>(result);
207         if (configuration == EnforceRange) {
208             exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range.");
209             return 0;
210         }
211         result %= LimitsTrait::numberOfValues;
212         return static_cast<T>(result > LimitsTrait::maxValue ? result - LimitsTrait::numberOfValues : result);
213     }
214
215     // Can the value be converted to a number?
216     V8TRYCATCH_EXCEPTION_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
217     if (numberObject.IsEmpty()) {
218         exceptionState.throwTypeError("Not convertible to a number value (of type '" + String(typeName) + "'.");
219         return 0;
220     }
221
222     if (configuration == EnforceRange)
223         return enforceRange(numberObject->Value(), LimitsTrait::minValue, LimitsTrait::maxValue, typeName, exceptionState);
224
225     double numberValue = numberObject->Value();
226     if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue)
227         return 0;
228
229     numberValue = numberValue < 0 ? -floor(fabs(numberValue)) : floor(fabs(numberValue));
230     numberValue = fmod(numberValue, LimitsTrait::numberOfValues);
231
232     return static_cast<T>(numberValue > LimitsTrait::maxValue ? numberValue - LimitsTrait::numberOfValues : numberValue);
233 }
234
235 template <typename T>
236 static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, const char* typeName, ExceptionState& exceptionState)
237 {
238     typedef IntTypeLimits<T> LimitsTrait;
239
240     // Fast case. The value is a 32-bit signed integer - possibly positive?
241     if (value->IsInt32()) {
242         int32_t result = value->Int32Value();
243         if (result >= 0 && result <= LimitsTrait::maxValue)
244             return static_cast<T>(result);
245         if (configuration == EnforceRange) {
246             exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range.");
247             return 0;
248         }
249         return static_cast<T>(result);
250     }
251
252     // Can the value be converted to a number?
253     V8TRYCATCH_EXCEPTION_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
254     if (numberObject.IsEmpty()) {
255         exceptionState.throwTypeError("Not convertible to a number value (of type '" + String(typeName) + "'.");
256         return 0;
257     }
258
259     if (configuration == EnforceRange)
260         return enforceRange(numberObject->Value(), 0, LimitsTrait::maxValue, typeName, exceptionState);
261
262     // Does the value convert to nan or to an infinity?
263     double numberValue = numberObject->Value();
264     if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue)
265         return 0;
266
267     if (configuration == Clamp)
268         return clampTo<T>(numberObject->Value());
269
270     numberValue = numberValue < 0 ? -floor(fabs(numberValue)) : floor(fabs(numberValue));
271     return static_cast<T>(fmod(numberValue, LimitsTrait::numberOfValues));
272 }
273
274 int8_t toInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
275 {
276     return toSmallerInt<int8_t>(value, configuration, "byte", exceptionState);
277 }
278
279 int8_t toInt8(v8::Handle<v8::Value> value)
280 {
281     NonThrowableExceptionState exceptionState;
282     return toInt8(value, NormalConversion, exceptionState);
283 }
284
285 uint8_t toUInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
286 {
287     return toSmallerUInt<uint8_t>(value, configuration, "octet", exceptionState);
288 }
289
290 uint8_t toUInt8(v8::Handle<v8::Value> value)
291 {
292     NonThrowableExceptionState exceptionState;
293     return toUInt8(value, NormalConversion, exceptionState);
294 }
295
296 int16_t toInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
297 {
298     return toSmallerInt<int16_t>(value, configuration, "short", exceptionState);
299 }
300
301 int16_t toInt16(v8::Handle<v8::Value> value)
302 {
303     NonThrowableExceptionState exceptionState;
304     return toInt16(value, NormalConversion, exceptionState);
305 }
306
307 uint16_t toUInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
308 {
309     return toSmallerUInt<uint16_t>(value, configuration, "unsigned short", exceptionState);
310 }
311
312 uint16_t toUInt16(v8::Handle<v8::Value> value)
313 {
314     NonThrowableExceptionState exceptionState;
315     return toUInt16(value, NormalConversion, exceptionState);
316 }
317
318 int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
319 {
320     // Fast case. The value is already a 32-bit integer.
321     if (value->IsInt32())
322         return value->Int32Value();
323
324     // Can the value be converted to a number?
325     V8TRYCATCH_EXCEPTION_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
326     if (numberObject.IsEmpty()) {
327         exceptionState.throwTypeError("Not convertible to a number value (of type 'long'.)");
328         return 0;
329     }
330
331     if (configuration == EnforceRange)
332         return enforceRange(numberObject->Value(), kMinInt32, kMaxInt32, "long", exceptionState);
333
334     // Does the value convert to nan or to an infinity?
335     double numberValue = numberObject->Value();
336     if (std::isnan(numberValue) || std::isinf(numberValue))
337         return 0;
338
339     if (configuration == Clamp)
340         return clampTo<int32_t>(numberObject->Value());
341
342     V8TRYCATCH_EXCEPTION_RETURN(int32_t, result, numberObject->Int32Value(), exceptionState, 0);
343     return result;
344 }
345
346 int32_t toInt32(v8::Handle<v8::Value> value)
347 {
348     NonThrowableExceptionState exceptionState;
349     return toInt32(value, NormalConversion, exceptionState);
350 }
351
352 uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
353 {
354     // Fast case. The value is already a 32-bit unsigned integer.
355     if (value->IsUint32())
356         return value->Uint32Value();
357
358     // Fast case. The value is a 32-bit signed integer - possibly positive?
359     if (value->IsInt32()) {
360         int32_t result = value->Int32Value();
361         if (result >= 0)
362             return result;
363         if (configuration == EnforceRange) {
364             exceptionState.throwTypeError("Value is outside the 'unsigned long' value range.");
365             return 0;
366         }
367         return result;
368     }
369
370     // Can the value be converted to a number?
371     V8TRYCATCH_EXCEPTION_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
372     if (numberObject.IsEmpty()) {
373         exceptionState.throwTypeError("Not convertible to a number value (of type 'unsigned long'.)");
374         return 0;
375     }
376
377     if (configuration == EnforceRange)
378         return enforceRange(numberObject->Value(), 0, kMaxUInt32, "unsigned long", exceptionState);
379
380     // Does the value convert to nan or to an infinity?
381     double numberValue = numberObject->Value();
382     if (std::isnan(numberValue) || std::isinf(numberValue))
383         return 0;
384
385     if (configuration == Clamp)
386         return clampTo<uint32_t>(numberObject->Value());
387
388     V8TRYCATCH_RETURN(uint32_t, result, numberObject->Uint32Value(), 0);
389     return result;
390 }
391
392 uint32_t toUInt32(v8::Handle<v8::Value> value)
393 {
394     NonThrowableExceptionState exceptionState;
395     return toUInt32(value, NormalConversion, exceptionState);
396 }
397
398 int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
399 {
400     // Fast case. The value is a 32-bit integer.
401     if (value->IsInt32())
402         return value->Int32Value();
403
404     // Can the value be converted to a number?
405     V8TRYCATCH_EXCEPTION_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
406     if (numberObject.IsEmpty()) {
407         exceptionState.throwTypeError("Not convertible to a number value (of type 'long long'.)");
408         return 0;
409     }
410
411     double x = numberObject->Value();
412
413     if (configuration == EnforceRange)
414         return enforceRange(x, -kJSMaxInteger, kJSMaxInteger, "long long", exceptionState);
415
416     // Does the value convert to nan or to an infinity?
417     if (std::isnan(x) || std::isinf(x))
418         return 0;
419
420     // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
421     unsigned long long integer;
422     doubleToInteger(x, integer);
423     return integer;
424 }
425
426 int64_t toInt64(v8::Handle<v8::Value> value)
427 {
428     NonThrowableExceptionState exceptionState;
429     return toInt64(value, NormalConversion, exceptionState);
430 }
431
432 uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
433 {
434     // Fast case. The value is a 32-bit unsigned integer.
435     if (value->IsUint32())
436         return value->Uint32Value();
437
438     // Fast case. The value is a 32-bit integer.
439     if (value->IsInt32()) {
440         int32_t result = value->Int32Value();
441         if (result >= 0)
442             return result;
443         if (configuration == EnforceRange) {
444             exceptionState.throwTypeError("Value is outside the 'unsigned long long' value range.");
445             return 0;
446         }
447         return result;
448     }
449
450     // Can the value be converted to a number?
451     V8TRYCATCH_EXCEPTION_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
452     if (numberObject.IsEmpty()) {
453         exceptionState.throwTypeError("Not convertible to a number value (of type 'unsigned long long'.)");
454         return 0;
455     }
456
457     double x = numberObject->Value();
458
459     if (configuration == EnforceRange)
460         return enforceRange(x, 0, kJSMaxInteger, "unsigned long long", exceptionState);
461
462     // Does the value convert to nan or to an infinity?
463     if (std::isnan(x) || std::isinf(x))
464         return 0;
465
466     // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
467     unsigned long long integer;
468     doubleToInteger(x, integer);
469     return integer;
470 }
471
472 uint64_t toUInt64(v8::Handle<v8::Value> value)
473 {
474     NonThrowableExceptionState exceptionState;
475     return toUInt64(value, NormalConversion, exceptionState);
476 }
477
478 float toFloat(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
479 {
480     V8TRYCATCH_EXCEPTION_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
481     return numberObject->NumberValue();
482 }
483
484 PassRefPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value> value, v8::Isolate* isolate)
485 {
486     RefPtr<XPathNSResolver> resolver;
487     if (V8XPathNSResolver::hasInstance(value, isolate))
488         resolver = V8XPathNSResolver::toNative(v8::Handle<v8::Object>::Cast(value));
489     else if (value->IsObject())
490         resolver = V8CustomXPathNSResolver::create(value->ToObject(), isolate);
491     return resolver;
492 }
493
494 v8::Handle<v8::Object> toInnerGlobalObject(v8::Handle<v8::Context> context)
495 {
496     return v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype());
497 }
498
499 DOMWindow* toDOMWindow(v8::Handle<v8::Context> context)
500 {
501     v8::Handle<v8::Object> global = context->Global();
502     ASSERT(!global.IsEmpty());
503     v8::Handle<v8::Object> window = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), MainWorld));
504     if (!window.IsEmpty())
505         return V8Window::toNative(window);
506     window = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), IsolatedWorld));
507     ASSERT(!window.IsEmpty());
508     return V8Window::toNative(window);
509 }
510
511 ExecutionContext* toExecutionContext(v8::Handle<v8::Context> context)
512 {
513     v8::Handle<v8::Object> global = context->Global();
514     v8::Handle<v8::Object> windowWrapper = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), MainWorld));
515     if (!windowWrapper.IsEmpty())
516         return V8Window::toNative(windowWrapper)->executionContext();
517     windowWrapper = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), IsolatedWorld));
518     if (!windowWrapper.IsEmpty())
519         return V8Window::toNative(windowWrapper)->executionContext();
520     v8::Handle<v8::Object> workerWrapper = global->FindInstanceInPrototypeChain(V8WorkerGlobalScope::domTemplate(context->GetIsolate(), WorkerWorld));
521     if (!workerWrapper.IsEmpty())
522         return V8WorkerGlobalScope::toNative(workerWrapper)->executionContext();
523     // FIXME: Is this line of code reachable?
524     return 0;
525 }
526
527 DOMWindow* activeDOMWindow()
528 {
529     v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCallingContext();
530     if (context.IsEmpty()) {
531         // Unfortunately, when processing script from a plug-in, we might not
532         // have a calling context. In those cases, we fall back to the
533         // entered context.
534         context = v8::Isolate::GetCurrent()->GetEnteredContext();
535     }
536     return toDOMWindow(context);
537 }
538
539 ExecutionContext* activeExecutionContext()
540 {
541     v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCallingContext();
542     if (context.IsEmpty()) {
543         // Unfortunately, when processing script from a plug-in, we might not
544         // have a calling context. In those cases, we fall back to the
545         // entered context.
546         context = v8::Isolate::GetCurrent()->GetEnteredContext();
547     }
548     return toExecutionContext(context);
549 }
550
551 DOMWindow* firstDOMWindow()
552 {
553     return toDOMWindow(v8::Isolate::GetCurrent()->GetEnteredContext());
554 }
555
556 Document* currentDocument()
557 {
558     return toDOMWindow(v8::Isolate::GetCurrent()->GetCurrentContext())->document();
559 }
560
561 Frame* toFrameIfNotDetached(v8::Handle<v8::Context> context)
562 {
563     DOMWindow* window = toDOMWindow(context);
564     if (window->isCurrentlyDisplayedInFrame())
565         return window->frame();
566     // We return 0 here because |context| is detached from the Frame. If we
567     // did return |frame| we could get in trouble because the frame could be
568     // navigated to another security origin.
569     return 0;
570 }
571
572 v8::Local<v8::Context> toV8Context(ExecutionContext* context, DOMWrapperWorld* world)
573 {
574     if (context->isDocument()) {
575         ASSERT(world);
576         if (Frame* frame = toDocument(context)->frame())
577             return frame->script().windowShell(world)->context();
578     } else if (context->isWorkerGlobalScope()) {
579         ASSERT(!world);
580         if (WorkerScriptController* script = toWorkerGlobalScope(context)->script())
581             return script->context();
582     }
583     return v8::Local<v8::Context>();
584 }
585
586 bool handleOutOfMemory()
587 {
588     v8::Local<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext();
589
590     if (!context->HasOutOfMemoryException())
591         return false;
592
593     // Warning, error, disable JS for this frame?
594     Frame* frame = toFrameIfNotDetached(context);
595     if (!frame)
596         return true;
597
598     frame->script().clearForOutOfMemory();
599     frame->loader().client()->didExhaustMemoryAvailableForScript();
600
601     if (Settings* settings = frame->settings())
602         settings->setScriptEnabled(false);
603
604     return true;
605 }
606
607 v8::Local<v8::Value> handleMaxRecursionDepthExceeded(v8::Isolate* isolate)
608 {
609     throwError(v8RangeError, "Maximum call stack size exceeded.", isolate);
610     return v8::Local<v8::Value>();
611 }
612
613 void crashIfV8IsDead()
614 {
615     if (v8::V8::IsDead()) {
616         // FIXME: We temporarily deal with V8 internal error situations
617         // such as out-of-memory by crashing the renderer.
618         CRASH();
619     }
620 }
621
622 WrapperWorldType worldType(v8::Isolate* isolate)
623 {
624     V8PerIsolateData* data = V8PerIsolateData::from(isolate);
625     if (!data->workerDOMDataStore())
626         return worldTypeInMainThread(isolate);
627     return WorkerWorld;
628 }
629
630 WrapperWorldType worldTypeInMainThread(v8::Isolate* isolate)
631 {
632     if (!DOMWrapperWorld::isolatedWorldsExist())
633         return MainWorld;
634     ASSERT(!isolate->GetEnteredContext().IsEmpty());
635     DOMWrapperWorld* isolatedWorld = DOMWrapperWorld::isolatedWorld(isolate->GetEnteredContext());
636     if (isolatedWorld)
637         return IsolatedWorld;
638     return MainWorld;
639 }
640
641 DOMWrapperWorld* isolatedWorldForIsolate(v8::Isolate* isolate)
642 {
643     V8PerIsolateData* data = V8PerIsolateData::from(isolate);
644     if (data->workerDOMDataStore())
645         return 0;
646     if (!DOMWrapperWorld::isolatedWorldsExist())
647         return 0;
648     ASSERT(isolate->InContext());
649     return DOMWrapperWorld::isolatedWorld(isolate->GetCurrentContext());
650 }
651
652 v8::Local<v8::Value> getHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, const char* key)
653 {
654     return getHiddenValue(isolate, object, v8AtomicString(isolate, key));
655 }
656
657 v8::Local<v8::Value> getHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, v8::Handle<v8::String> key)
658 {
659     return object->GetHiddenValue(key);
660 }
661
662 bool setHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, const char* key, v8::Handle<v8::Value> value)
663 {
664     return setHiddenValue(isolate, object, v8AtomicString(isolate, key), value);
665 }
666
667 bool setHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, v8::Handle<v8::String> key, v8::Handle<v8::Value> value)
668 {
669     return object->SetHiddenValue(key, value);
670 }
671
672 bool deleteHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, const char* key)
673 {
674     return deleteHiddenValue(isolate, object, v8AtomicString(isolate, key));
675 }
676
677 bool deleteHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, v8::Handle<v8::String> key)
678 {
679     return object->DeleteHiddenValue(key);
680 }
681
682 v8::Local<v8::Value> getHiddenValueFromMainWorldWrapper(v8::Isolate* isolate, ScriptWrappable* wrappable, const char* key)
683 {
684     return getHiddenValueFromMainWorldWrapper(isolate, wrappable, v8AtomicString(isolate, key));
685 }
686
687 v8::Local<v8::Value> getHiddenValueFromMainWorldWrapper(v8::Isolate* isolate, ScriptWrappable* wrappable, v8::Handle<v8::String> key)
688 {
689     v8::Local<v8::Object> wrapper = wrappable->newLocalWrapper(isolate);
690     return wrapper.IsEmpty() ? v8::Local<v8::Value>() : getHiddenValue(isolate, wrapper, key);
691 }
692
693 static gin::IsolateHolder* mainIsolateHolder = 0;
694
695 v8::Isolate* mainThreadIsolate()
696 {
697     ASSERT(mainIsolateHolder);
698     ASSERT(isMainThread());
699     return mainIsolateHolder->isolate();
700 }
701
702 void setMainThreadIsolate(v8::Isolate* isolate)
703 {
704     ASSERT(!mainIsolateHolder || !isolate);
705     ASSERT(isMainThread());
706     if (isolate) {
707         mainIsolateHolder = new gin::IsolateHolder(isolate);
708     } else {
709         delete mainIsolateHolder;
710         mainIsolateHolder = 0;
711     }
712 }
713
714 v8::Isolate* toIsolate(ExecutionContext* context)
715 {
716     if (context && context->isDocument())
717         return mainThreadIsolate();
718     return v8::Isolate::GetCurrent();
719 }
720
721 v8::Isolate* toIsolate(Frame* frame)
722 {
723     return frame->script().isolate();
724 }
725
726 } // namespace WebCore