2 * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
32 #include "bindings/core/v8/V8Binding.h"
34 #include "bindings/core/v8/ScriptController.h"
35 #include "bindings/core/v8/V8AbstractEventListener.h"
36 #include "bindings/core/v8/V8BindingMacros.h"
37 #include "bindings/core/v8/V8Element.h"
38 #include "bindings/core/v8/V8NodeFilter.h"
39 #include "bindings/core/v8/V8NodeFilterCondition.h"
40 #include "bindings/core/v8/V8ObjectConstructor.h"
41 #include "bindings/core/v8/V8Window.h"
42 #include "bindings/core/v8/V8WorkerGlobalScope.h"
43 #include "bindings/core/v8/V8XPathNSResolver.h"
44 #include "bindings/core/v8/WindowProxy.h"
45 #include "bindings/core/v8/WorkerScriptController.h"
46 #include "bindings/core/v8/custom/V8CustomXPathNSResolver.h"
47 #include "core/dom/Document.h"
48 #include "core/dom/Element.h"
49 #include "core/dom/NodeFilter.h"
50 #include "core/dom/QualifiedName.h"
51 #include "core/frame/LocalFrame.h"
52 #include "core/frame/Settings.h"
53 #include "core/inspector/BindingVisitors.h"
54 #include "core/inspector/InspectorTraceEvents.h"
55 #include "core/loader/FrameLoader.h"
56 #include "core/loader/FrameLoaderClient.h"
57 #include "core/workers/WorkerGlobalScope.h"
58 #include "core/xml/XPathNSResolver.h"
59 #include "platform/EventTracer.h"
60 #include "platform/JSONValues.h"
61 #include "wtf/ArrayBufferContents.h"
62 #include "wtf/MainThread.h"
63 #include "wtf/MathExtras.h"
64 #include "wtf/StdLibExtras.h"
65 #include "wtf/Threading.h"
66 #include "wtf/text/AtomicString.h"
67 #include "wtf/text/CString.h"
68 #include "wtf/text/StringBuffer.h"
69 #include "wtf/text/StringHash.h"
70 #include "wtf/text/WTFString.h"
71 #include "wtf/unicode/CharacterNames.h"
72 #include "wtf/unicode/Unicode.h"
76 void setArityTypeError(ExceptionState& exceptionState, const char* valid, unsigned provided)
78 exceptionState.throwTypeError(ExceptionMessages::invalidArity(valid, provided));
81 v8::Local<v8::Value> createMinimumArityTypeErrorForMethod(const char* method, const char* type, unsigned expected, unsigned provided, v8::Isolate* isolate)
83 return V8ThrowException::createTypeError(ExceptionMessages::failedToExecute(method, type, ExceptionMessages::notEnoughArguments(expected, provided)), isolate);
86 v8::Local<v8::Value> createMinimumArityTypeErrorForConstructor(const char* type, unsigned expected, unsigned provided, v8::Isolate* isolate)
88 return V8ThrowException::createTypeError(ExceptionMessages::failedToConstruct(type, ExceptionMessages::notEnoughArguments(expected, provided)), isolate);
91 void setMinimumArityTypeError(ExceptionState& exceptionState, unsigned expected, unsigned provided)
93 exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(expected, provided));
96 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
97 virtual void* Allocate(size_t size) OVERRIDE
100 WTF::ArrayBufferContents::allocateMemory(size, WTF::ArrayBufferContents::ZeroInitialize, data);
104 virtual void* AllocateUninitialized(size_t size) OVERRIDE
107 WTF::ArrayBufferContents::allocateMemory(size, WTF::ArrayBufferContents::DontInitialize, data);
111 virtual void Free(void* data, size_t size) OVERRIDE
113 WTF::ArrayBufferContents::freeMemory(data, size);
117 v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator()
119 DEFINE_STATIC_LOCAL(ArrayBufferAllocator, arrayBufferAllocator, ());
120 return &arrayBufferAllocator;
123 PassRefPtrWillBeRawPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback, v8::Handle<v8::Object> creationContext, ScriptState* scriptState)
125 if (callback->IsNull())
127 RefPtrWillBeRawPtr<NodeFilter> filter = NodeFilter::create();
129 v8::Handle<v8::Object> filterWrapper = toV8(filter, creationContext, scriptState->isolate()).As<v8::Object>();
131 RefPtrWillBeRawPtr<NodeFilterCondition> condition = V8NodeFilterCondition::create(callback, filterWrapper, scriptState);
132 filter->setCondition(condition.release());
134 return filter.release();
137 const int32_t kMaxInt32 = 0x7fffffff;
138 const int32_t kMinInt32 = -kMaxInt32 - 1;
139 const uint32_t kMaxUInt32 = 0xffffffff;
140 const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, maximum uniquely representable integer in ECMAScript.
142 static double enforceRange(double x, double minimum, double maximum, const char* typeName, ExceptionState& exceptionState)
144 if (std::isnan(x) || std::isinf(x)) {
145 exceptionState.throwTypeError("Value is" + String(std::isinf(x) ? " infinite and" : "") + " not of type '" + String(typeName) + "'.");
149 if (x < minimum || x > maximum) {
150 exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range.");
156 template <typename T>
157 struct IntTypeLimits {
161 struct IntTypeLimits<int8_t> {
162 static const int8_t minValue = -128;
163 static const int8_t maxValue = 127;
164 static const unsigned numberOfValues = 256; // 2^8
168 struct IntTypeLimits<uint8_t> {
169 static const uint8_t maxValue = 255;
170 static const unsigned numberOfValues = 256; // 2^8
174 struct IntTypeLimits<int16_t> {
175 static const short minValue = -32768;
176 static const short maxValue = 32767;
177 static const unsigned numberOfValues = 65536; // 2^16
181 struct IntTypeLimits<uint16_t> {
182 static const unsigned short maxValue = 65535;
183 static const unsigned numberOfValues = 65536; // 2^16
186 template <typename T>
187 static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, const char* typeName, ExceptionState& exceptionState)
189 typedef IntTypeLimits<T> LimitsTrait;
191 // Fast case. The value is already a 32-bit integer in the right range.
192 if (value->IsInt32()) {
193 int32_t result = value->Int32Value();
194 if (result >= LimitsTrait::minValue && result <= LimitsTrait::maxValue)
195 return static_cast<T>(result);
196 if (configuration == EnforceRange) {
197 exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range.");
200 result %= LimitsTrait::numberOfValues;
201 return static_cast<T>(result > LimitsTrait::maxValue ? result - LimitsTrait::numberOfValues : result);
204 // Can the value be converted to a number?
205 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
206 if (numberObject.IsEmpty()) {
207 exceptionState.throwTypeError("Not convertible to a number value (of type '" + String(typeName) + "'.");
211 if (configuration == EnforceRange)
212 return enforceRange(numberObject->Value(), LimitsTrait::minValue, LimitsTrait::maxValue, typeName, exceptionState);
214 double numberValue = numberObject->Value();
215 if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue)
218 numberValue = numberValue < 0 ? -floor(fabs(numberValue)) : floor(fabs(numberValue));
219 numberValue = fmod(numberValue, LimitsTrait::numberOfValues);
221 return static_cast<T>(numberValue > LimitsTrait::maxValue ? numberValue - LimitsTrait::numberOfValues : numberValue);
224 template <typename T>
225 static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, const char* typeName, ExceptionState& exceptionState)
227 typedef IntTypeLimits<T> LimitsTrait;
229 // Fast case. The value is a 32-bit signed integer - possibly positive?
230 if (value->IsInt32()) {
231 int32_t result = value->Int32Value();
232 if (result >= 0 && result <= LimitsTrait::maxValue)
233 return static_cast<T>(result);
234 if (configuration == EnforceRange) {
235 exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range.");
238 return static_cast<T>(result);
241 // Can the value be converted to a number?
242 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
243 if (numberObject.IsEmpty()) {
244 exceptionState.throwTypeError("Not convertible to a number value (of type '" + String(typeName) + "'.");
248 if (configuration == EnforceRange)
249 return enforceRange(numberObject->Value(), 0, LimitsTrait::maxValue, typeName, exceptionState);
251 // Does the value convert to nan or to an infinity?
252 double numberValue = numberObject->Value();
253 if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue)
256 if (configuration == Clamp)
257 return clampTo<T>(numberObject->Value());
259 numberValue = numberValue < 0 ? -floor(fabs(numberValue)) : floor(fabs(numberValue));
260 return static_cast<T>(fmod(numberValue, LimitsTrait::numberOfValues));
263 int8_t toInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
265 return toSmallerInt<int8_t>(value, configuration, "byte", exceptionState);
268 int8_t toInt8(v8::Handle<v8::Value> value)
270 NonThrowableExceptionState exceptionState;
271 return toInt8(value, NormalConversion, exceptionState);
274 uint8_t toUInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
276 return toSmallerUInt<uint8_t>(value, configuration, "octet", exceptionState);
279 uint8_t toUInt8(v8::Handle<v8::Value> value)
281 NonThrowableExceptionState exceptionState;
282 return toUInt8(value, NormalConversion, exceptionState);
285 int16_t toInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
287 return toSmallerInt<int16_t>(value, configuration, "short", exceptionState);
290 int16_t toInt16(v8::Handle<v8::Value> value)
292 NonThrowableExceptionState exceptionState;
293 return toInt16(value, NormalConversion, exceptionState);
296 uint16_t toUInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
298 return toSmallerUInt<uint16_t>(value, configuration, "unsigned short", exceptionState);
301 uint16_t toUInt16(v8::Handle<v8::Value> value)
303 NonThrowableExceptionState exceptionState;
304 return toUInt16(value, NormalConversion, exceptionState);
307 int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
309 // Fast case. The value is already a 32-bit integer.
310 if (value->IsInt32())
311 return value->Int32Value();
313 // Can the value be converted to a number?
314 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
315 if (numberObject.IsEmpty()) {
316 exceptionState.throwTypeError("Not convertible to a number value (of type 'long'.)");
320 if (configuration == EnforceRange)
321 return enforceRange(numberObject->Value(), kMinInt32, kMaxInt32, "long", exceptionState);
323 // Does the value convert to nan or to an infinity?
324 double numberValue = numberObject->Value();
325 if (std::isnan(numberValue) || std::isinf(numberValue))
328 if (configuration == Clamp)
329 return clampTo<int32_t>(numberObject->Value());
331 TONATIVE_DEFAULT_EXCEPTIONSTATE(int32_t, result, numberObject->Int32Value(), exceptionState, 0);
335 int32_t toInt32(v8::Handle<v8::Value> value)
337 NonThrowableExceptionState exceptionState;
338 return toInt32(value, NormalConversion, exceptionState);
341 uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
343 // Fast case. The value is already a 32-bit unsigned integer.
344 if (value->IsUint32())
345 return value->Uint32Value();
347 // Fast case. The value is a 32-bit signed integer - possibly positive?
348 if (value->IsInt32()) {
349 int32_t result = value->Int32Value();
352 if (configuration == EnforceRange) {
353 exceptionState.throwTypeError("Value is outside the 'unsigned long' value range.");
359 // Can the value be converted to a number?
360 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
361 if (numberObject.IsEmpty()) {
362 exceptionState.throwTypeError("Not convertible to a number value (of type 'unsigned long'.)");
366 if (configuration == EnforceRange)
367 return enforceRange(numberObject->Value(), 0, kMaxUInt32, "unsigned long", exceptionState);
369 // Does the value convert to nan or to an infinity?
370 double numberValue = numberObject->Value();
371 if (std::isnan(numberValue) || std::isinf(numberValue))
374 if (configuration == Clamp)
375 return clampTo<uint32_t>(numberObject->Value());
377 TONATIVE_DEFAULT(uint32_t, result, numberObject->Uint32Value(), 0);
381 uint32_t toUInt32(v8::Handle<v8::Value> value)
383 NonThrowableExceptionState exceptionState;
384 return toUInt32(value, NormalConversion, exceptionState);
387 int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
389 // Fast case. The value is a 32-bit integer.
390 if (value->IsInt32())
391 return value->Int32Value();
393 // Can the value be converted to a number?
394 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
395 if (numberObject.IsEmpty()) {
396 exceptionState.throwTypeError("Not convertible to a number value (of type 'long long'.)");
400 double x = numberObject->Value();
402 if (configuration == EnforceRange)
403 return enforceRange(x, -kJSMaxInteger, kJSMaxInteger, "long long", exceptionState);
405 // Does the value convert to nan or to an infinity?
406 if (std::isnan(x) || std::isinf(x))
409 // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
410 unsigned long long integer;
411 doubleToInteger(x, integer);
415 int64_t toInt64(v8::Handle<v8::Value> value)
417 NonThrowableExceptionState exceptionState;
418 return toInt64(value, NormalConversion, exceptionState);
421 uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState)
423 // Fast case. The value is a 32-bit unsigned integer.
424 if (value->IsUint32())
425 return value->Uint32Value();
427 // Fast case. The value is a 32-bit integer.
428 if (value->IsInt32()) {
429 int32_t result = value->Int32Value();
432 if (configuration == EnforceRange) {
433 exceptionState.throwTypeError("Value is outside the 'unsigned long long' value range.");
439 // Can the value be converted to a number?
440 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
441 if (numberObject.IsEmpty()) {
442 exceptionState.throwTypeError("Not convertible to a number value (of type 'unsigned long long'.)");
446 double x = numberObject->Value();
448 if (configuration == EnforceRange)
449 return enforceRange(x, 0, kJSMaxInteger, "unsigned long long", exceptionState);
451 // Does the value convert to nan or to an infinity?
452 if (std::isnan(x) || std::isinf(x))
455 // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
456 unsigned long long integer;
457 doubleToInteger(x, integer);
461 uint64_t toUInt64(v8::Handle<v8::Value> value)
463 NonThrowableExceptionState exceptionState;
464 return toUInt64(value, NormalConversion, exceptionState);
467 float toFloat(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
469 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0);
470 return numberObject->NumberValue();
473 String toByteString(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
475 // Handle null default value.
479 // From the Web IDL spec: http://heycam.github.io/webidl/#es-ByteString
483 // 1. Let x be ToString(v)
484 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::String>, stringObject, value->ToString(), exceptionState, String());
485 String x = toCoreString(stringObject);
487 // 2. If the value of any element of x is greater than 255, then throw a TypeError.
488 if (!x.containsOnlyLatin1()) {
489 exceptionState.throwTypeError("Value is not a valid ByteString.");
493 // 3. Return an IDL ByteString value whose length is the length of x, and where the
494 // value of each element is the value of the corresponding element of x.
495 // Blink: A ByteString is simply a String with a range constrained per the above, so
496 // this is the identity operation.
500 static bool hasUnmatchedSurrogates(const String& string)
502 // By definition, 8-bit strings are confined to the Latin-1 code page and
503 // have no surrogates, matched or otherwise.
507 const UChar* characters = string.characters16();
508 const unsigned length = string.length();
510 for (unsigned i = 0; i < length; ++i) {
511 UChar c = characters[i];
512 if (U16_IS_SINGLE(c))
516 ASSERT(U16_IS_LEAD(c));
519 UChar d = characters[i + 1];
520 if (!U16_IS_TRAIL(d))
527 // Replace unmatched surrogates with REPLACEMENT CHARACTER U+FFFD.
528 static String replaceUnmatchedSurrogates(const String& string)
530 // This roughly implements http://heycam.github.io/webidl/#dfn-obtain-unicode
531 // but since Blink strings are 16-bits internally, the output is simply
532 // re-encoded to UTF-16.
534 // The concept of surrogate pairs is explained at:
535 // http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G2630
537 // Blink-specific optimization to avoid making an unnecessary copy.
538 if (!hasUnmatchedSurrogates(string))
540 ASSERT(!string.is8Bit());
542 // 1. Let S be the DOMString value.
543 const UChar* s = string.characters16();
545 // 2. Let n be the length of S.
546 const unsigned n = string.length();
548 // 3. Initialize i to 0.
551 // 4. Initialize U to be an empty sequence of Unicode characters.
553 u.reserveCapacity(n);
557 // 1. Let c be the code unit in S at index i.
559 // 2. Depending on the value of c:
560 if (U16_IS_SINGLE(c)) {
561 // c < 0xD800 or c > 0xDFFF
562 // Append to U the Unicode character with code point c.
564 } else if (U16_IS_TRAIL(c)) {
565 // 0xDC00 <= c <= 0xDFFF
566 // Append to U a U+FFFD REPLACEMENT CHARACTER.
567 u.append(WTF::Unicode::replacementCharacter);
569 // 0xD800 <= c <= 0xDBFF
570 ASSERT(U16_IS_LEAD(c));
572 // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT CHARACTER.
573 u.append(WTF::Unicode::replacementCharacter);
575 // 2. Otherwise, i < n−1:
577 // ....1. Let d be the code unit in S at index i+1.
579 if (U16_IS_TRAIL(d)) {
580 // 2. If 0xDC00 <= d <= 0xDFFF, then:
581 // ..1. Let a be c & 0x3FF.
582 // ..2. Let b be d & 0x3FF.
583 // ..3. Append to U the Unicode character with code point 2^16+2^10*a+b.
584 u.append(U16_GET_SUPPLEMENTARY(c, d));
585 // Blink: This is equivalent to u.append(c); u.append(d);
588 // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a U+FFFD REPLACEMENT CHARACTER.
589 u.append(WTF::Unicode::replacementCharacter);
598 ASSERT(u.length() == string.length());
602 String toScalarValueString(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
604 // From the Encoding standard (with a TODO to move to Web IDL):
605 // http://encoding.spec.whatwg.org/#type-scalarvaluestring
608 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::String>, stringObject, value->ToString(), exceptionState, String());
610 // ScalarValueString is identical to DOMString except that "convert a
611 // DOMString to a sequence of Unicode characters" is used subsequently
612 // when converting to an IDL value
613 String x = toCoreString(stringObject);
614 return replaceUnmatchedSurrogates(x);
617 PassRefPtrWillBeRawPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value> value, v8::Isolate* isolate)
619 RefPtrWillBeRawPtr<XPathNSResolver> resolver = nullptr;
620 if (V8XPathNSResolver::hasInstance(value, isolate))
621 resolver = V8XPathNSResolver::toNative(v8::Handle<v8::Object>::Cast(value));
622 else if (value->IsObject())
623 resolver = V8CustomXPathNSResolver::create(value->ToObject(), isolate);
627 LocalDOMWindow* toDOMWindow(v8::Handle<v8::Value> value, v8::Isolate* isolate)
629 if (value.IsEmpty() || !value->IsObject())
632 v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(v8::Handle<v8::Object>::Cast(value), isolate);
633 if (!windowWrapper.IsEmpty())
634 return V8Window::toNative(windowWrapper);
638 LocalDOMWindow* toDOMWindow(v8::Handle<v8::Context> context)
640 if (context.IsEmpty())
642 return toDOMWindow(context->Global(), context->GetIsolate());
645 LocalDOMWindow* enteredDOMWindow(v8::Isolate* isolate)
647 LocalDOMWindow* window = toDOMWindow(isolate->GetEnteredContext());
649 // We don't always have an entered DOM window, for example during microtask callbacks from V8
650 // (where the entered context may be the DOM-in-JS context). In that case, we fall back
651 // to the current context.
652 window = currentDOMWindow(isolate);
658 LocalDOMWindow* currentDOMWindow(v8::Isolate* isolate)
660 return toDOMWindow(isolate->GetCurrentContext());
663 LocalDOMWindow* callingDOMWindow(v8::Isolate* isolate)
665 v8::Handle<v8::Context> context = isolate->GetCallingContext();
666 if (context.IsEmpty()) {
667 // Unfortunately, when processing script from a plug-in, we might not
668 // have a calling context. In those cases, we fall back to the
670 context = isolate->GetEnteredContext();
672 return toDOMWindow(context);
675 ExecutionContext* toExecutionContext(v8::Handle<v8::Context> context)
677 if (context.IsEmpty())
679 v8::Handle<v8::Object> global = context->Global();
680 v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(global, context->GetIsolate());
681 if (!windowWrapper.IsEmpty())
682 return V8Window::toNative(windowWrapper)->executionContext();
683 v8::Handle<v8::Object> workerWrapper = V8WorkerGlobalScope::findInstanceInPrototypeChain(global, context->GetIsolate());
684 if (!workerWrapper.IsEmpty())
685 return V8WorkerGlobalScope::toNative(workerWrapper)->executionContext();
686 // FIXME: Is this line of code reachable?
690 ExecutionContext* currentExecutionContext(v8::Isolate* isolate)
692 return toExecutionContext(isolate->GetCurrentContext());
695 ExecutionContext* callingExecutionContext(v8::Isolate* isolate)
697 v8::Handle<v8::Context> context = isolate->GetCallingContext();
698 if (context.IsEmpty()) {
699 // Unfortunately, when processing script from a plug-in, we might not
700 // have a calling context. In those cases, we fall back to the
702 context = isolate->GetEnteredContext();
704 return toExecutionContext(context);
707 LocalFrame* toFrameIfNotDetached(v8::Handle<v8::Context> context)
709 LocalDOMWindow* window = toDOMWindow(context);
710 if (window && window->isCurrentlyDisplayedInFrame())
711 return window->frame();
712 // We return 0 here because |context| is detached from the LocalFrame. If we
713 // did return |frame| we could get in trouble because the frame could be
714 // navigated to another security origin.
718 v8::Local<v8::Context> toV8Context(ExecutionContext* context, DOMWrapperWorld& world)
721 if (context->isDocument()) {
722 if (LocalFrame* frame = toDocument(context)->frame())
723 return frame->script().windowProxy(world)->context();
724 } else if (context->isWorkerGlobalScope()) {
725 if (WorkerScriptController* script = toWorkerGlobalScope(context)->script())
726 return script->context();
728 return v8::Local<v8::Context>();
731 v8::Local<v8::Context> toV8Context(LocalFrame* frame, DOMWrapperWorld& world)
734 return v8::Local<v8::Context>();
735 v8::Local<v8::Context> context = frame->script().windowProxy(world)->context();
736 if (context.IsEmpty())
737 return v8::Local<v8::Context>();
738 LocalFrame* attachedFrame= toFrameIfNotDetached(context);
739 return frame == attachedFrame ? context : v8::Local<v8::Context>();
742 void crashIfV8IsDead()
744 if (v8::V8::IsDead()) {
745 // FIXME: We temporarily deal with V8 internal error situations
746 // such as out-of-memory by crashing the renderer.
751 v8::Handle<v8::Function> getBoundFunction(v8::Handle<v8::Function> function)
753 v8::Handle<v8::Value> boundFunction = function->GetBoundFunction();
754 return boundFunction->IsFunction() ? v8::Handle<v8::Function>::Cast(boundFunction) : function;
757 void addHiddenValueToArray(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int arrayIndex, v8::Isolate* isolate)
759 v8::Local<v8::Value> arrayValue = object->GetInternalField(arrayIndex);
760 if (arrayValue->IsNull() || arrayValue->IsUndefined()) {
761 arrayValue = v8::Array::New(isolate);
762 object->SetInternalField(arrayIndex, arrayValue);
765 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(arrayValue);
766 array->Set(v8::Integer::New(isolate, array->Length()), value);
769 void removeHiddenValueFromArray(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int arrayIndex, v8::Isolate* isolate)
771 v8::Local<v8::Value> arrayValue = object->GetInternalField(arrayIndex);
772 if (!arrayValue->IsArray())
774 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(arrayValue);
775 for (int i = array->Length() - 1; i >= 0; --i) {
776 v8::Local<v8::Value> item = array->Get(v8::Integer::New(isolate, i));
777 if (item->StrictEquals(value)) {
784 void moveEventListenerToNewWrapper(v8::Handle<v8::Object> object, EventListener* oldValue, v8::Local<v8::Value> newValue, int arrayIndex, v8::Isolate* isolate)
787 V8AbstractEventListener* oldListener = V8AbstractEventListener::cast(oldValue);
789 v8::Local<v8::Object> oldListenerObject = oldListener->getExistingListenerObject();
790 if (!oldListenerObject.IsEmpty())
791 removeHiddenValueFromArray(object, oldListenerObject, arrayIndex, isolate);
794 // Non-callable input is treated as null and ignored
795 if (newValue->IsFunction())
796 addHiddenValueToArray(object, newValue, arrayIndex, isolate);
799 v8::Isolate* toIsolate(ExecutionContext* context)
801 if (context && context->isDocument())
802 return V8PerIsolateData::mainThreadIsolate();
803 return v8::Isolate::GetCurrent();
806 v8::Isolate* toIsolate(LocalFrame* frame)
809 return frame->script().isolate();
812 PassRefPtr<JSONValue> v8ToJSONValue(v8::Isolate* isolate, v8::Handle<v8::Value> value, int maxDepth)
814 if (value.IsEmpty()) {
815 ASSERT_NOT_REACHED();
823 if (value->IsNull() || value->IsUndefined())
824 return JSONValue::null();
825 if (value->IsBoolean())
826 return JSONBasicValue::create(value->BooleanValue());
827 if (value->IsNumber())
828 return JSONBasicValue::create(value->NumberValue());
829 if (value->IsString())
830 return JSONString::create(toCoreString(value.As<v8::String>()));
831 if (value->IsArray()) {
832 v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
833 RefPtr<JSONArray> inspectorArray = JSONArray::create();
834 uint32_t length = array->Length();
835 for (uint32_t i = 0; i < length; i++) {
836 v8::Local<v8::Value> value = array->Get(v8::Int32::New(isolate, i));
837 RefPtr<JSONValue> element = v8ToJSONValue(isolate, value, maxDepth);
840 inspectorArray->pushValue(element);
842 return inspectorArray;
844 if (value->IsObject()) {
845 RefPtr<JSONObject> jsonObject = JSONObject::create();
846 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
847 v8::Local<v8::Array> propertyNames = object->GetPropertyNames();
848 uint32_t length = propertyNames->Length();
849 for (uint32_t i = 0; i < length; i++) {
850 v8::Local<v8::Value> name = propertyNames->Get(v8::Int32::New(isolate, i));
851 // FIXME(yurys): v8::Object should support GetOwnPropertyNames
852 if (name->IsString() && !object->HasRealNamedProperty(v8::Handle<v8::String>::Cast(name)))
854 RefPtr<JSONValue> propertyValue = v8ToJSONValue(isolate, object->Get(name), maxDepth);
857 TOSTRING_DEFAULT(V8StringResource<TreatNullAsNullString>, nameString, name, nullptr);
858 jsonObject->setValue(nameString, propertyValue);
862 ASSERT_NOT_REACHED();
866 V8TestingScope::V8TestingScope(v8::Isolate* isolate)
867 : m_handleScope(isolate)
868 , m_contextScope(v8::Context::New(isolate))
869 , m_scriptState(ScriptStateForTesting::create(isolate->GetCurrentContext(), DOMWrapperWorld::create()))
873 V8TestingScope::~V8TestingScope()
875 m_scriptState->disposePerContextData();
878 ScriptState* V8TestingScope::scriptState() const
880 return m_scriptState.get();
883 v8::Isolate* V8TestingScope::isolate() const
885 return m_scriptState->isolate();
888 void GetDevToolsFunctionInfo(v8::Handle<v8::Function> function, v8::Isolate* isolate, int& scriptId, String& resourceName, int& lineNumber)
890 v8::Handle<v8::Function> originalFunction = getBoundFunction(function);
891 scriptId = originalFunction->ScriptId();
892 v8::ScriptOrigin origin = originalFunction->GetScriptOrigin();
893 if (!origin.ResourceName().IsEmpty()) {
894 resourceName = NativeValueTraits<String>::nativeValue(origin.ResourceName(), isolate);
895 lineNumber = originalFunction->GetScriptLineNumber() + 1;
897 if (resourceName.isEmpty()) {
898 resourceName = "undefined";
903 PassRefPtr<TraceEvent::ConvertableToTraceFormat> devToolsTraceEventData(ExecutionContext* context, v8::Handle<v8::Function> function, v8::Isolate* isolate)
908 GetDevToolsFunctionInfo(function, isolate, scriptId, resourceName, lineNumber);
909 return InspectorFunctionCallEvent::data(context, scriptId, resourceName, lineNumber);