diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/bindings/v8 | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/bindings/v8')
248 files changed, 9206 insertions, 8673 deletions
diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ArrayValue.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ArrayValue.cpp index 1280548b9f6..065fd2f8815 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ArrayValue.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ArrayValue.cpp @@ -62,7 +62,7 @@ bool ArrayValue::get(size_t index, Dictionary& value) const ASSERT(m_isolate); ASSERT(m_isolate == v8::Isolate::GetCurrent()); - v8::Local<v8::Value> indexedValue = m_array->Get(v8::Integer::NewFromUnsigned(index, m_isolate)); + v8::Local<v8::Value> indexedValue = m_array->Get(v8::Integer::NewFromUnsigned(m_isolate, index)); if (indexedValue.IsEmpty() || !indexedValue->IsObject()) return false; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.cpp b/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.cpp index 7f9db62257d..126b2ba6519 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.cpp @@ -34,65 +34,69 @@ #include "bindings/v8/V8Binding.h" #include "core/dom/Document.h" #include "core/html/HTMLFrameElementBase.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" #include "platform/weborigin/SecurityOrigin.h" namespace WebCore { -static bool isDocumentAccessibleFromDOMWindow(Document* targetDocument, DOMWindow* activeWindow) +static bool isDocumentAccessibleFromDOMWindow(Document* targetDocument, LocalDOMWindow* callingWindow) { if (!targetDocument) return false; - if (!activeWindow) + if (!callingWindow) return false; - if (activeWindow->document()->securityOrigin()->canAccess(targetDocument->securityOrigin())) + if (callingWindow->document()->securityOrigin()->canAccess(targetDocument->securityOrigin())) return true; return false; } -static bool canAccessDocument(Document* targetDocument, ExceptionState& exceptionState) +static bool canAccessDocument(v8::Isolate* isolate, Document* targetDocument, ExceptionState& exceptionState) { - DOMWindow* activeWindow = activeDOMWindow(); - if (isDocumentAccessibleFromDOMWindow(targetDocument, activeWindow)) + LocalDOMWindow* callingWindow = callingDOMWindow(isolate); + if (isDocumentAccessibleFromDOMWindow(targetDocument, callingWindow)) return true; if (targetDocument->domWindow()) - exceptionState.throwSecurityError(targetDocument->domWindow()->sanitizedCrossDomainAccessErrorMessage(activeWindow), targetDocument->domWindow()->crossDomainAccessErrorMessage(activeWindow)); + exceptionState.throwSecurityError(targetDocument->domWindow()->sanitizedCrossDomainAccessErrorMessage(callingWindow), targetDocument->domWindow()->crossDomainAccessErrorMessage(callingWindow)); return false; } -static bool canAccessDocument(Document* targetDocument, SecurityReportingOption reportingOption = ReportSecurityError) +static bool canAccessDocument(v8::Isolate* isolate, Document* targetDocument, SecurityReportingOption reportingOption = ReportSecurityError) { - DOMWindow* activeWindow = activeDOMWindow(); - if (isDocumentAccessibleFromDOMWindow(targetDocument, activeWindow)) + LocalDOMWindow* callingWindow = callingDOMWindow(isolate); + if (isDocumentAccessibleFromDOMWindow(targetDocument, callingWindow)) return true; if (reportingOption == ReportSecurityError && targetDocument->domWindow()) { - if (Frame* frame = targetDocument->frame()) - frame->domWindow()->printErrorMessage(targetDocument->domWindow()->crossDomainAccessErrorMessage(activeWindow)); + if (LocalFrame* frame = targetDocument->frame()) + frame->domWindow()->printErrorMessage(targetDocument->domWindow()->crossDomainAccessErrorMessage(callingWindow)); } return false; } -bool BindingSecurity::shouldAllowAccessToFrame(Frame* target, SecurityReportingOption reportingOption) +bool BindingSecurity::shouldAllowAccessToFrame(v8::Isolate* isolate, Frame* target, SecurityReportingOption reportingOption) { - return target && canAccessDocument(target->document(), reportingOption); + if (!target || !target->isLocalFrame()) + return false; + return canAccessDocument(isolate, toLocalFrame(target)->document(), reportingOption); } -bool BindingSecurity::shouldAllowAccessToFrame(Frame* target, ExceptionState& exceptionState) +bool BindingSecurity::shouldAllowAccessToFrame(v8::Isolate* isolate, Frame* target, ExceptionState& exceptionState) { - return target && canAccessDocument(target->document(), exceptionState); + if (!target || !target->isLocalFrame()) + return false; + return canAccessDocument(isolate, toLocalFrame(target)->document(), exceptionState); } -bool BindingSecurity::shouldAllowAccessToNode(Node* target, ExceptionState& exceptionState) +bool BindingSecurity::shouldAllowAccessToNode(v8::Isolate* isolate, Node* target, ExceptionState& exceptionState) { - return target && canAccessDocument(&target->document(), exceptionState); + return target && canAccessDocument(isolate, &target->document(), exceptionState); } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.h b/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.h index 253a7f25781..b6e5bba893d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.h @@ -31,13 +31,15 @@ #ifndef BindingSecurity_h #define BindingSecurity_h +// FIXME: The LocalFrame include should not be necessary, clients should be including it where they use it. +#include "core/frame/LocalFrame.h" #include "wtf/text/WTFString.h" +#include <v8.h> namespace WebCore { -class DOMWindow; +class LocalDOMWindow; class ExceptionState; -class Frame; class Node; enum SecurityReportingOption { @@ -47,9 +49,9 @@ enum SecurityReportingOption { class BindingSecurity { public: - static bool shouldAllowAccessToNode(Node*, ExceptionState&); - static bool shouldAllowAccessToFrame(Frame*, SecurityReportingOption = ReportSecurityError); - static bool shouldAllowAccessToFrame(Frame*, ExceptionState&); + static bool shouldAllowAccessToNode(v8::Isolate*, Node*, ExceptionState&); + static bool shouldAllowAccessToFrame(v8::Isolate*, Frame*, SecurityReportingOption = ReportSecurityError); + static bool shouldAllowAccessToFrame(v8::Isolate*, Frame*, ExceptionState&); }; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CallbackPromiseAdapter.h b/chromium/third_party/WebKit/Source/bindings/v8/CallbackPromiseAdapter.h index 19b5a543918..21719792209 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CallbackPromiseAdapter.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/CallbackPromiseAdapter.h @@ -31,8 +31,7 @@ #ifndef CallbackPromiseAdapter_h #define CallbackPromiseAdapter_h -#include "bindings/v8/DOMRequestState.h" -#include "bindings/v8/ScriptPromiseResolver.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" #include "public/platform/WebCallbacks.h" namespace WebCore { @@ -40,16 +39,25 @@ namespace WebCore { // This class provides an easy way to convert from a Script-exposed // class (i.e. a class that has a toV8() overload) that uses Promises // to a WebKit API class that uses WebCallbacks. You can define -// seperate Success and Error classes, but this example just uses one +// separate Success and Error classes, but this example just uses one // object for both. // // To use: // // class MyClass ... { // typedef blink::WebMyClass WebType; -// static PassRefPtr<MyClass> from(blink::WebMyClass* webInstance) { +// static PassRefPtr<MyClass> from(ScriptPromiseResolverWithContext* resolver, +// blink::WebMyClass* webInstance) { // // convert/create as appropriate, but often it's just: // return MyClass::create(adoptPtr(webInstance)); +// +// // Since promise resolving is done as an async task, it's not +// // guaranteed that the script context has seen the promise resolve +// // immediately after calling onSuccess/onError. You can use the +// // ScriptPromise from the resolver to schedule a task that executes +// // after resolving: +// ScriptState::Scope scope(resolver->scriptState()); +// resolver->promise().then(...); // } // // Now when calling into a WebKit API that requires a WebCallbacks<blink::WebMyClass, blink::WebMyClass>*: @@ -61,28 +69,24 @@ namespace WebCore { // example that ownership of the WebCallbacks instance is being passed // in and it is up to the callee to free the WebCallbacks instace. template<typename S, typename T> -class CallbackPromiseAdapter : public blink::WebCallbacks<typename S::WebType, typename T::WebType> { +class CallbackPromiseAdapter FINAL : public blink::WebCallbacks<typename S::WebType, typename T::WebType> { public: - explicit CallbackPromiseAdapter(PassRefPtr<ScriptPromiseResolver> resolver, ExecutionContext* context) + CallbackPromiseAdapter(PassRefPtr<ScriptPromiseResolverWithContext> resolver) : m_resolver(resolver) - , m_requestState(context) { } virtual ~CallbackPromiseAdapter() { } virtual void onSuccess(typename S::WebType* result) OVERRIDE { - DOMRequestState::Scope scope(m_requestState); - m_resolver->resolve(S::from(result)); + m_resolver->resolve(S::from(m_resolver.get(), result)); } - void onError(typename T::WebType* error) OVERRIDE + virtual void onError(typename T::WebType* error) OVERRIDE { - DOMRequestState::Scope scope(m_requestState); - m_resolver->reject(T::from(error)); + m_resolver->reject(T::from(m_resolver.get(), error)); } private: - RefPtr<ScriptPromiseResolver> m_resolver; - DOMRequestState m_requestState; + RefPtr<ScriptPromiseResolverWithContext> m_resolver; WTF_MAKE_NONCOPYABLE(CallbackPromiseAdapter); }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.cpp b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.cpp index 25ba61792f3..7a692394496 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.cpp @@ -43,7 +43,7 @@ CustomElementBinding::CustomElementBinding(v8::Isolate* isolate, v8::Handle<v8:: , m_prototype(isolate, prototype) , m_wrapperType(wrapperType) { - ASSERT(m_prototype.value()); + ASSERT(!m_prototype.isEmpty()); ASSERT(m_wrapperType); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.h b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.h index 3fa394a0b09..b989e361823 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.h @@ -31,7 +31,7 @@ #ifndef CustomElementBinding_h #define CustomElementBinding_h -#include "bindings/v8/UnsafePersistent.h" +#include "bindings/v8/ScopedPersistent.h" #include "wtf/PassOwnPtr.h" #include <v8.h> @@ -43,7 +43,7 @@ class CustomElementBinding { public: static PassOwnPtr<CustomElementBinding> create(v8::Isolate*, v8::Handle<v8::Object> prototype, const WrapperTypeInfo*); - ~CustomElementBinding() { m_prototype.dispose(); } + ~CustomElementBinding() { } v8::Handle<v8::Object> prototype() { return m_prototype.newLocal(m_isolate); } const WrapperTypeInfo* wrapperType() { return m_wrapperType; } @@ -52,7 +52,7 @@ private: CustomElementBinding(v8::Isolate*, v8::Handle<v8::Object> prototype, const WrapperTypeInfo*); v8::Isolate* m_isolate; - UnsafePersistent<v8::Object> m_prototype; + ScopedPersistent<v8::Object> m_prototype; const WrapperTypeInfo* m_wrapperType; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp index b13466635ae..a8e43a1012e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp @@ -31,20 +31,18 @@ #include "config.h" #include "bindings/v8/CustomElementConstructorBuilder.h" -#include "HTMLNames.h" -#include "SVGNames.h" -#include "V8Document.h" -#include "V8HTMLElementWrapperFactory.h" -#include "V8SVGElementWrapperFactory.h" +#include "bindings/core/v8/V8Document.h" #include "bindings/v8/CustomElementBinding.h" #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/Dictionary.h" #include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ScriptState.h" -#include "bindings/v8/UnsafePersistent.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8PerContextData.h" +#include "core/HTMLNames.h" +#include "core/SVGNames.h" +#include "core/V8HTMLElementWrapperFactory.h" // FIXME: should be bindings/core/v8 +#include "core/V8SVGElementWrapperFactory.h" // FIXME: should be bindings/core/v8 #include "core/dom/Document.h" #include "core/dom/custom/CustomElementCallbackDispatcher.h" #include "core/dom/custom/CustomElementDefinition.h" @@ -56,44 +54,58 @@ namespace WebCore { static void constructCustomElement(const v8::FunctionCallbackInfo<v8::Value>&); -CustomElementConstructorBuilder::CustomElementConstructorBuilder(ScriptState* state, const Dictionary* options) - : m_context(state->context()) +CustomElementConstructorBuilder::CustomElementConstructorBuilder(ScriptState* scriptState, const Dictionary* options) + : m_scriptState(scriptState) , m_options(options) , m_wrapperType(0) { - ASSERT(m_context == v8::Isolate::GetCurrent()->GetCurrentContext()); + ASSERT(m_scriptState->context() == m_scriptState->isolate()->GetCurrentContext()); } bool CustomElementConstructorBuilder::isFeatureAllowed() const { - // Check that we are in the main world - return !DOMWrapperWorld::isolatedWorld(m_context); + return m_scriptState->world().isMainWorld(); } bool CustomElementConstructorBuilder::validateOptions(const AtomicString& type, QualifiedName& tagName, ExceptionState& exceptionState) { ASSERT(m_prototype.IsEmpty()); + v8::TryCatch tryCatch; + ScriptValue prototypeScriptValue; if (m_options->get("prototype", prototypeScriptValue) && !prototypeScriptValue.isNull()) { + ASSERT(!tryCatch.HasCaught()); if (!prototypeScriptValue.isObject()) { CustomElementException::throwException(CustomElementException::PrototypeNotAnObject, type, exceptionState); + tryCatch.ReThrow(); return false; } m_prototype = prototypeScriptValue.v8Value().As<v8::Object>(); - } else { - m_prototype = v8::Object::New(); - v8::Local<v8::Object> basePrototype = V8PerContextData::from(m_context)->prototypeForType(&V8HTMLElement::wrapperTypeInfo); + } else if (!tryCatch.HasCaught()) { + m_prototype = v8::Object::New(m_scriptState->isolate()); + v8::Local<v8::Object> basePrototype = m_scriptState->perContextData()->prototypeForType(&V8HTMLElement::wrapperTypeInfo); if (!basePrototype.IsEmpty()) m_prototype->SetPrototype(basePrototype); } - String extends; + if (tryCatch.HasCaught()) { + tryCatch.ReThrow(); + return false; + } + + AtomicString extends; bool extendsProvidedAndNonNull = m_options->get("extends", extends); - if (!V8PerContextData::from(m_context)) { + if (tryCatch.HasCaught()) { + tryCatch.ReThrow(); + return false; + } + + if (!m_scriptState->perContextData()) { // FIXME: This should generate an InvalidContext exception at a later point. CustomElementException::throwException(CustomElementException::ContextDestroyedCheckingPrototype, type, exceptionState); + tryCatch.ReThrow(); return false; } @@ -101,6 +113,8 @@ bool CustomElementConstructorBuilder::validateOptions(const AtomicString& type, if (hasValidPrototypeChainFor(&V8SVGElement::wrapperTypeInfo)) namespaceURI = SVGNames::svgNamespaceURI; + ASSERT(!tryCatch.HasCaught()); + AtomicString localName; if (extendsProvidedAndNonNull) { @@ -108,15 +122,18 @@ bool CustomElementConstructorBuilder::validateOptions(const AtomicString& type, if (!Document::isValidName(localName)) { CustomElementException::throwException(CustomElementException::ExtendsIsInvalidName, type, exceptionState); + tryCatch.ReThrow(); return false; } if (CustomElement::isValidName(localName)) { CustomElementException::throwException(CustomElementException::ExtendsIsCustomElementName, type, exceptionState); + tryCatch.ReThrow(); return false; } } else { if (namespaceURI == SVGNames::svgNamespaceURI) { CustomElementException::throwException(CustomElementException::ExtendsIsInvalidName, type, exceptionState); + tryCatch.ReThrow(); return false; } localName = type; @@ -129,6 +146,7 @@ bool CustomElementConstructorBuilder::validateOptions(const AtomicString& type, else m_wrapperType = findWrapperTypeForSVGTagName(localName); + ASSERT(!tryCatch.HasCaught()); ASSERT(m_wrapperType); tagName = QualifiedName(nullAtom, localName, namespaceURI); return m_wrapperType; @@ -138,18 +156,16 @@ PassRefPtr<CustomElementLifecycleCallbacks> CustomElementConstructorBuilder::cre { ASSERT(!m_prototype.IsEmpty()); - RefPtr<ExecutionContext> executionContext(toExecutionContext(m_context)); - v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); - v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Isolate* isolate = m_scriptState->isolate(); v8::Handle<v8::Function> created = retrieveCallback(isolate, "createdCallback"); v8::Handle<v8::Function> attached = retrieveCallback(isolate, "attachedCallback"); v8::Handle<v8::Function> detached = retrieveCallback(isolate, "detachedCallback"); v8::Handle<v8::Function> attributeChanged = retrieveCallback(isolate, "attributeChangedCallback"); - m_callbacks = V8CustomElementLifecycleCallbacks::create(executionContext.get(), m_prototype, created, attached, detached, attributeChanged); + m_callbacks = V8CustomElementLifecycleCallbacks::create(m_scriptState.get(), m_prototype, created, attached, detached, attributeChanged); return m_callbacks.get(); } @@ -167,7 +183,7 @@ bool CustomElementConstructorBuilder::createConstructor(Document* document, Cust ASSERT(m_constructor.IsEmpty()); ASSERT(document); - v8::Isolate* isolate = m_context->GetIsolate(); + v8::Isolate* isolate = m_scriptState->isolate(); if (!prototypeIsValid(definition->descriptor().type(), exceptionState)) return false; @@ -191,10 +207,10 @@ bool CustomElementConstructorBuilder::createConstructor(Document* document, Cust m_constructor->SetName(v8Type->IsNull() ? v8TagName : v8Type.As<v8::String>()); - V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "customElementDocument", toV8(document, m_context->Global(), isolate)); - V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "customElementNamespaceURI", v8String(isolate, descriptor.namespaceURI())); - V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "customElementTagName", v8TagName); - V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "customElementType", v8Type); + V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customElementDocument(isolate), toV8(document, m_scriptState->context()->Global(), isolate)); + V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customElementNamespaceURI(isolate), v8String(isolate, descriptor.namespaceURI())); + V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customElementTagName(isolate), v8TagName); + V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customElementType(isolate), v8Type); v8::Handle<v8::String> prototypeKey = v8String(isolate, "prototype"); ASSERT(m_constructor->HasOwnProperty(prototypeKey)); @@ -207,7 +223,7 @@ bool CustomElementConstructorBuilder::createConstructor(Document* document, Cust // property. m_constructor->ForceSet(prototypeKey, m_prototype, v8::PropertyAttribute(v8::ReadOnly | v8::DontEnum | v8::DontDelete)); - V8HiddenPropertyName::setNamedHiddenReference(m_prototype, "customElementIsInterfacePrototypeObject", v8::True(isolate)); + V8HiddenValue::setHiddenValue(isolate, m_prototype, V8HiddenValue::customElementIsInterfacePrototypeObject(isolate), v8::True(isolate)); m_prototype->ForceSet(v8String(isolate, "constructor"), m_constructor, v8::DontEnum); return true; @@ -215,12 +231,12 @@ bool CustomElementConstructorBuilder::createConstructor(Document* document, Cust bool CustomElementConstructorBuilder::prototypeIsValid(const AtomicString& type, ExceptionState& exceptionState) const { - if (m_prototype->InternalFieldCount() || !m_prototype->GetHiddenValue(V8HiddenPropertyName::customElementIsInterfacePrototypeObject(m_context->GetIsolate())).IsEmpty()) { + if (m_prototype->InternalFieldCount() || !V8HiddenValue::getHiddenValue(m_scriptState->isolate(), m_prototype, V8HiddenValue::customElementIsInterfacePrototypeObject(m_scriptState->isolate())).IsEmpty()) { CustomElementException::throwException(CustomElementException::PrototypeInUse, type, exceptionState); return false; } - if (m_prototype->GetPropertyAttributes(v8String(m_context->GetIsolate(), "constructor")) & v8::DontDelete) { + if (m_prototype->GetPropertyAttributes(v8String(m_scriptState->isolate(), "constructor")) & v8::DontDelete) { CustomElementException::throwException(CustomElementException::ConstructorPropertyNotConfigurable, type, exceptionState); return false; } @@ -232,17 +248,17 @@ bool CustomElementConstructorBuilder::didRegisterDefinition(CustomElementDefinit { ASSERT(!m_constructor.IsEmpty()); - return m_callbacks->setBinding(definition, CustomElementBinding::create(m_context->GetIsolate(), m_prototype, m_wrapperType)); + return m_callbacks->setBinding(definition, CustomElementBinding::create(m_scriptState->isolate(), m_prototype, m_wrapperType)); } ScriptValue CustomElementConstructorBuilder::bindingsReturnValue() const { - return ScriptValue(m_constructor, m_context->GetIsolate()); + return ScriptValue(m_scriptState.get(), m_constructor); } bool CustomElementConstructorBuilder::hasValidPrototypeChainFor(const WrapperTypeInfo* type) const { - v8::Handle<v8::Object> elementPrototype = V8PerContextData::from(m_context)->prototypeForType(type); + v8::Handle<v8::Object> elementPrototype = m_scriptState->perContextData()->prototypeForType(type); if (elementPrototype.IsEmpty()) return false; @@ -266,22 +282,28 @@ static void constructCustomElement(const v8::FunctionCallbackInfo<v8::Value>& in } if (info.Length() > 0) { - throwUninformativeAndGenericTypeError(isolate); + throwTypeError("This constructor should be called without arguments.", isolate); return; } - Document* document = V8Document::toNative(info.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementDocument(isolate)).As<v8::Object>()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, info.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementNamespaceURI(isolate))); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, tagName, info.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementTagName(isolate))); - v8::Handle<v8::Value> maybeType = info.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementType(isolate)); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, maybeType); + Document* document = V8Document::toNative(V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Callee(), V8HiddenValue::customElementDocument(isolate)).As<v8::Object>()); + TOSTRING_VOID(V8StringResource<>, namespaceURI, V8HiddenValue::getHiddenValue(isolate, info.Callee(), V8HiddenValue::customElementNamespaceURI(isolate))); + TOSTRING_VOID(V8StringResource<>, tagName, V8HiddenValue::getHiddenValue(isolate, info.Callee(), V8HiddenValue::customElementTagName(isolate))); + v8::Handle<v8::Value> maybeType = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Callee(), V8HiddenValue::customElementType(isolate)); + TOSTRING_VOID(V8StringResource<>, type, maybeType); ExceptionState exceptionState(ExceptionState::ConstructionContext, "CustomElement", info.Holder(), info.GetIsolate()); CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; - RefPtr<Element> element = document->createElementNS(namespaceURI, tagName, maybeType->IsNull() ? nullAtom : type, exceptionState); + RefPtrWillBeRawPtr<Element> element = document->createElementNS(namespaceURI, tagName, maybeType->IsNull() ? nullAtom : type, exceptionState); if (exceptionState.throwIfNeeded()) return; +#if ENABLE(OILPAN) + // FIXME: Oilpan: We don't have RawPtr<Eement> version of + // v8SetReturnValueFast until Node.idl has WillBeGarbageCollected. + v8SetReturnValueFast(info, element.get(), document); +#else v8SetReturnValueFast(info, element.release(), document); +#endif } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.h b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.h index 21f81e8c787..623244d2a70 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.h @@ -49,7 +49,6 @@ class Document; class Element; class ExceptionState; class QualifiedName; -class ScriptState; class V8PerContextData; struct WrapperTypeInfo; @@ -82,7 +81,7 @@ private: bool prototypeIsValid(const AtomicString& type, ExceptionState&) const; v8::Handle<v8::Function> retrieveCallback(v8::Isolate*, const char* name); - v8::Handle<v8::Context> m_context; + RefPtr<ScriptState> m_scriptState; const Dictionary* m_options; v8::Handle<v8::Object> m_prototype; const WrapperTypeInfo* m_wrapperType; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.cpp b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.cpp index 128c1e417e2..abd8830ea8b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.cpp @@ -31,13 +31,13 @@ #include "config.h" #include "bindings/v8/CustomElementWrapper.h" -#include "V8HTMLElement.h" -#include "V8HTMLElementWrapperFactory.h" -#include "V8SVGElement.h" -#include "V8SVGElementWrapperFactory.h" +#include "bindings/core/v8/V8HTMLElement.h" +#include "bindings/core/v8/V8SVGElement.h" #include "bindings/v8/DOMDataStore.h" #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/V8PerContextData.h" +#include "core/V8HTMLElementWrapperFactory.h" // FIXME: should be bindings/core/v8 +#include "core/V8SVGElementWrapperFactory.h" // FIXME: should be bindings/core/v8 #include "core/dom/custom/CustomElement.h" #include "core/html/HTMLElement.h" #include "core/html/HTMLUnknownElement.h" @@ -86,23 +86,21 @@ v8::Handle<v8::Object> createUpgradeCandidateWrapper(ElementType* element, v8::H } template<typename ElementType, typename WrapperType> -v8::Handle<v8::Object> CustomElementWrapper<ElementType, WrapperType>::wrap(PassRefPtr<ElementType> element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate, v8::Handle<v8::Object> (*createSpecificWrapper)(ElementType* element, v8::Handle<v8::Object> creationContext, v8::Isolate*)) +v8::Handle<v8::Object> CustomElementWrapper<ElementType, WrapperType>::wrap(PassRefPtrWillBeRawPtr<ElementType> element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate, v8::Handle<v8::Object> (*createSpecificWrapper)(ElementType* element, v8::Handle<v8::Object> creationContext, v8::Isolate*)) { ASSERT(DOMDataStore::getWrapper<V8Element>(element.get(), isolate).IsEmpty()); - // FIXME: creationContext.IsEmpty() should never happen. Remove - // this when callers (like InspectorController::inspect) are fixed - // to never pass an empty creation context. - v8::Handle<v8::Context> context = creationContext.IsEmpty() ? isolate->GetCurrentContext() : creationContext->CreationContext(); + ASSERT(!creationContext.IsEmpty()); + v8::Handle<v8::Context> context = creationContext->CreationContext(); - if (!element->isUpgradedCustomElement() || DOMWrapperWorld::isolatedWorld(context)) + if (!element->isUpgradedCustomElement() || DOMWrapperWorld::world(context).isIsolatedWorld()) return createUpgradeCandidateWrapper(element.get(), creationContext, isolate, createSpecificWrapper); V8PerContextData* perContextData = V8PerContextData::from(context); if (!perContextData) return v8::Handle<v8::Object>(); - CustomElementBinding* binding = perContextData->customElementBinding(CustomElement::definitionFor(element.get())); + CustomElementBinding* binding = perContextData->customElementBinding(element->customElementDefinition()); v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, binding->wrapperType(), element.get(), isolate); if (wrapper.IsEmpty()) return v8::Handle<v8::Object>(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.h b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.h index c3cbbe8e58d..bf3ba6e8dce 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.h @@ -31,6 +31,7 @@ #ifndef CustomElementWrapper_h #define CustomElementWrapper_h +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include <v8.h> @@ -47,7 +48,7 @@ private: friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v8::Object>, v8::Isolate*); friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8::Object>, v8::Isolate*); - static v8::Handle<v8::Object> wrap(PassRefPtr<ElementType>, v8::Handle<v8::Object> creationContext, v8::Isolate*, v8::Handle<v8::Object> (*createSpecificWrapper)(ElementType* element, v8::Handle<v8::Object> creationContext, v8::Isolate*)); + static v8::Handle<v8::Object> wrap(PassRefPtrWillBeRawPtr<ElementType>, v8::Handle<v8::Object> creationContext, v8::Isolate*, v8::Handle<v8::Object> (*createSpecificWrapper)(ElementType* element, v8::Handle<v8::Object> creationContext, v8::Isolate*)); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.cpp b/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.cpp index fcfb12f00e7..c9ef7c4195c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.cpp @@ -37,40 +37,21 @@ namespace WebCore { -DOMDataStore::DOMDataStore(WrapperWorldType type) - : m_type(type) +DOMDataStore::DOMDataStore(bool isMainWorld) + : m_isMainWorld(isMainWorld) , m_wrapperMap(v8::Isolate::GetCurrent()) // FIXME Don't call GetCurrent twice. { - V8PerIsolateData::current()->registerDOMDataStore(this); } DOMDataStore::~DOMDataStore() { - ASSERT(m_type != MainWorld); // We never actually destruct the main world's DOMDataStore. - V8PerIsolateData::current()->unregisterDOMDataStore(this); + ASSERT(!m_isMainWorld); // We never actually destruct the main world's DOMDataStore. m_wrapperMap.clear(); } -DOMDataStore& DOMDataStore::mainWorldStore() -{ - DEFINE_STATIC_LOCAL(DOMDataStore, mainWorldDOMDataStore, (MainWorld)); - ASSERT(isMainThread()); - return mainWorldDOMDataStore; -} - DOMDataStore& DOMDataStore::current(v8::Isolate* isolate) { - V8PerIsolateData* data = isolate ? V8PerIsolateData::from(isolate) : V8PerIsolateData::current(); - if (UNLIKELY(!!data->workerDOMDataStore())) - return *data->workerDOMDataStore(); - - if (DOMWrapperWorld::isolatedWorldsExist()) { - DOMWrapperWorld* isolatedWorld = DOMWrapperWorld::isolatedWorld(isolate->GetEnteredContext()); - if (UNLIKELY(!!isolatedWorld)) - return isolatedWorld->isolatedWorldDOMDataStore(); - } - - return mainWorldStore(); + return DOMWrapperWorld::current(isolate).domDataStore(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.h b/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.h index a75d38f02d5..852e8110a32 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.h @@ -46,24 +46,39 @@ class Node; class DOMDataStore { WTF_MAKE_NONCOPYABLE(DOMDataStore); public: - explicit DOMDataStore(WrapperWorldType); + explicit DOMDataStore(bool isMainWorld); ~DOMDataStore(); static DOMDataStore& current(v8::Isolate*); + // We can use a wrapper stored in a ScriptWrappable when we're in the main world. + // This method does the fast check if we're in the main world. If this method returns true, + // it is guaranteed that we're in the main world. On the other hand, if this method returns + // false, nothing is guaranteed (we might be in the main world). + template<typename T> + static bool canUseScriptWrappable(T* object) + { + return !DOMWrapperWorld::isolatedWorldsExist() + && !canExistInWorker(object) + && ScriptWrappable::wrapperCanBeStoredInObject(object); + } + template<typename V8T, typename T, typename Wrappable> static bool setReturnValueFromWrapperFast(v8::ReturnValue<v8::Value> returnValue, T* object, v8::Local<v8::Object> holder, Wrappable* wrappable) { - // What we'd really like to check here is whether we're in the - // main world or in an isolated world. The fastest way to do that - // is to check that there is no isolated world and the 'object' - // is an object that can exist in the main world. The second fastest - // way is to check whether the wrappable's wrapper is the same as - // the holder. - if ((!DOMWrapperWorld::isolatedWorldsExist() && !canExistInWorker(object)) || holderContainsWrapper(holder, wrappable)) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object)) - return ScriptWrappable::setReturnValueWithSecurityCheck<V8T>(returnValue, object); - return mainWorldStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); + if (canUseScriptWrappable(object)) { + ScriptWrappable::assertWrapperSanity<V8T, T>(object, object); + return ScriptWrappable::fromObject(object)->setReturnValue(returnValue); + } + // The second fastest way to check if we're in the main world is to check if + // the wrappable's wrapper is the same as the holder. + // FIXME: Investigate if it's worth having this check for performance. + if (holderContainsWrapper(holder, wrappable)) { + if (ScriptWrappable::wrapperCanBeStoredInObject(object)) { + ScriptWrappable::assertWrapperSanity<V8T, T>(object, object); + return ScriptWrappable::fromObject(object)->setReturnValue(returnValue); + } + return DOMWrapperWorld::mainWorld().domDataStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); } return current(returnValue.GetIsolate()).template setReturnValueFrom<V8T>(returnValue, object); } @@ -71,9 +86,9 @@ public: template<typename V8T, typename T> static bool setReturnValueFromWrapper(v8::ReturnValue<v8::Value> returnValue, T* object) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && !canExistInWorker(object)) { - if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) - return ScriptWrappable::setReturnValueWithSecurityCheck<V8T>(returnValue, object); + if (canUseScriptWrappable(object)) { + ScriptWrappable::assertWrapperSanity<V8T, T>(object, object); + return ScriptWrappable::fromObject(object)->setReturnValue(returnValue); } return current(returnValue.GetIsolate()).template setReturnValueFrom<V8T>(returnValue, object); } @@ -82,20 +97,18 @@ public: static bool setReturnValueFromWrapperForMainWorld(v8::ReturnValue<v8::Value> returnValue, T* object) { if (ScriptWrappable::wrapperCanBeStoredInObject(object)) - return ScriptWrappable::setReturnValue(returnValue, object); - return mainWorldStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); + return ScriptWrappable::fromObject(object)->setReturnValue(returnValue); + return DOMWrapperWorld::mainWorld().domDataStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); } template<typename V8T, typename T> static v8::Handle<v8::Object> getWrapper(T* object, v8::Isolate* isolate) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && !canExistInWorker(object)) { - if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) { - v8::Handle<v8::Object> result = ScriptWrappable::getUnsafeWrapperFromObject(object).newLocal(isolate); - // Security: always guard against malicious tampering. - RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result.IsEmpty() || result->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(object)); - return result; - } + if (canUseScriptWrappable(object)) { + v8::Handle<v8::Object> result = ScriptWrappable::fromObject(object)->newLocalWrapper(isolate); + // Security: always guard against malicious tampering. + ScriptWrappable::assertWrapperSanity<V8T, T>(result, object); + return result; } return current(isolate).template get<V8T>(object, isolate); } @@ -103,13 +116,10 @@ public: template<typename V8T, typename T> static void setWrapperReference(const v8::Persistent<v8::Object>& parent, T* child, v8::Isolate* isolate) { - if (ScriptWrappable::wrapperCanBeStoredInObject(child) && !canExistInWorker(child)) { - if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) { - UnsafePersistent<v8::Object> unsafePersistent = ScriptWrappable::getUnsafeWrapperFromObject(child); - // Security: always guard against malicious tampering. - RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(unsafePersistent.isEmpty() || unsafePersistent.value()->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(child)); - unsafePersistent.setReferenceFrom(parent, isolate); - } + if (canUseScriptWrappable(child)) { + ScriptWrappable::assertWrapperSanity<V8T, T>(child, child); + ScriptWrappable::fromObject(child)->setReference(parent, isolate); + return; } current(isolate).template setReference<V8T>(parent, child, isolate); } @@ -117,11 +127,9 @@ public: template<typename V8T, typename T> static void setWrapper(T* object, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && !canExistInWorker(object)) { - if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) { - ScriptWrappable::setWrapperInObject(object, wrapper, isolate, configuration); - return; - } + if (canUseScriptWrappable(object)) { + ScriptWrappable::fromObject(object)->setWrapper(wrapper, isolate, configuration); + return; } return current(isolate).template set<V8T>(object, wrapper, isolate, configuration); } @@ -135,16 +143,16 @@ public: template<typename V8T, typename T> inline v8::Handle<v8::Object> get(T* object, v8::Isolate* isolate) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) - return ScriptWrappable::getUnsafeWrapperFromObject(object).newLocal(isolate); + if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld) + return ScriptWrappable::fromObject(object)->newLocalWrapper(isolate); return m_wrapperMap.newLocal(V8T::toInternalPointer(object), isolate); } template<typename V8T, typename T> inline void setReference(const v8::Persistent<v8::Object>& parent, T* child, v8::Isolate* isolate) { - if (ScriptWrappable::wrapperCanBeStoredInObject(child) && m_type == MainWorld) { - ScriptWrappable::getUnsafeWrapperFromObject(child).setReferenceFrom(parent, isolate); + if (ScriptWrappable::wrapperCanBeStoredInObject(child) && m_isMainWorld) { + ScriptWrappable::fromObject(child)->setReference(parent, isolate); return; } m_wrapperMap.setReference(parent, V8T::toInternalPointer(child), isolate); @@ -153,16 +161,16 @@ public: template<typename V8T, typename T> inline bool setReturnValueFrom(v8::ReturnValue<v8::Value> returnValue, T* object) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) - return ScriptWrappable::setReturnValue(returnValue, object); + if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld) + return ScriptWrappable::fromObject(object)->setReturnValue(returnValue); return m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); } template<typename V8T, typename T> inline bool containsWrapper(T* object) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) - return !ScriptWrappable::getUnsafeWrapperFromObject(object).isEmpty(); + if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld) + return ScriptWrappable::fromObject(object)->containsWrapper(); return m_wrapperMap.containsKey(V8T::toInternalPointer(object)); } @@ -172,15 +180,13 @@ private: { ASSERT(!!object); ASSERT(!wrapper.IsEmpty()); - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) { - ScriptWrappable::setWrapperInObject(object, wrapper, isolate, configuration); + if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld) { + ScriptWrappable::fromObject(object)->setWrapper(wrapper, isolate, configuration); return; } m_wrapperMap.set(V8T::toInternalPointer(object), wrapper, configuration); } - static DOMDataStore& mainWorldStore(); - static bool canExistInWorker(void*) { return true; } static bool canExistInWorker(Node*) { return false; } @@ -192,12 +198,12 @@ private: static bool holderContainsWrapper(v8::Local<v8::Object> holder, ScriptWrappable* wrappable) { // Verify our assumptions about the main world. - UnsafePersistent<v8::Object> unsafePersistent = wrappable->unsafePersistent(); - ASSERT(unsafePersistent.isEmpty() || !(holder == *unsafePersistent.persistent()) || current(v8::Isolate::GetCurrent()).m_type == MainWorld); - return holder == *unsafePersistent.persistent(); + ASSERT(wrappable); + ASSERT(!wrappable->containsWrapper() || !wrappable->isEqualTo(holder) || current(v8::Isolate::GetCurrent()).m_isMainWorld); + return wrappable->isEqualTo(holder); } - WrapperWorldType m_type; + bool m_isMainWorld; DOMWrapperMap<void> m_wrapperMap; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMRequestState.h b/chromium/third_party/WebKit/Source/bindings/v8/DOMRequestState.h deleted file mode 100644 index 710f3d371b0..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMRequestState.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DOMRequestState_h -#define DOMRequestState_h - -#include "bindings/v8/DOMWrapperWorld.h" -#include "bindings/v8/V8Binding.h" -#include "core/dom/ExecutionContext.h" -#include "v8.h" -#include "wtf/RefPtr.h" - -namespace WebCore { - -class DOMRequestState { -public: - explicit DOMRequestState(ExecutionContext* executionContext) - : m_executionContext(executionContext) - , m_world(DOMWrapperWorld::current()) - , m_isolate(toIsolate(executionContext)) - { - ASSERT(m_executionContext); - } - - void clear() - { - m_executionContext = 0; - m_world.clear(); - } - - class Scope { - public: - explicit Scope(DOMRequestState& state) - : m_handleScope(state.isolate()) - , m_contextScope(state.context()) - { - } - private: - v8::HandleScope m_handleScope; - v8::Context::Scope m_contextScope; - }; - - v8::Local<v8::Context> context() - { - ASSERT(m_executionContext); - return toV8Context(m_executionContext, m_world.get()); - } - - v8::Isolate* isolate() const - { - return m_isolate; - } - - bool isValid() const { return m_executionContext; } - -private: - ExecutionContext* m_executionContext; - RefPtr<DOMWrapperWorld> m_world; - v8::Isolate* m_isolate; -}; - -} -#endif diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperMap.h b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperMap.h index 5987f57ace8..1ebbc53fb7c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperMap.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperMap.h @@ -31,9 +31,8 @@ #ifndef DOMWrapperMap_h #define DOMWrapperMap_h -#include "bindings/v8/UnsafePersistent.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/WrapperTypeInfo.h" +#include <v8-util.h> #include <v8.h> #include "wtf/HashMap.h" @@ -42,96 +41,127 @@ namespace WebCore { template<class KeyType> class DOMWrapperMap { public: - typedef HashMap<KeyType*, UnsafePersistent<v8::Object> > MapType; - explicit DOMWrapperMap(v8::Isolate* isolate) : m_isolate(isolate) + , m_map(isolate) { } v8::Handle<v8::Object> newLocal(KeyType* key, v8::Isolate* isolate) { - return m_map.get(key).newLocal(isolate); + return m_map.Get(key); } bool setReturnValueFrom(v8::ReturnValue<v8::Value> returnValue, KeyType* key) { - typename MapType::iterator it = m_map.find(key); - if (it == m_map.end()) - return false; - returnValue.Set(*(it->value.persistent())); - return true; + return m_map.SetReturnValue(key, returnValue); } void setReference(const v8::Persistent<v8::Object>& parent, KeyType* key, v8::Isolate* isolate) { - m_map.get(key).setReferenceFrom(parent, isolate); + m_map.SetReference(key, parent); } bool containsKey(KeyType* key) { - return m_map.find(key) != m_map.end(); - } - - bool containsKeyAndValue(KeyType* key, v8::Handle<v8::Object> value) - { - typename MapType::iterator it = m_map.find(key); - if (it == m_map.end()) - return false; - return *(it->value.persistent()) == value; + return m_map.Contains(key); } void set(KeyType* key, v8::Handle<v8::Object> wrapper, const WrapperConfiguration& configuration) { ASSERT(static_cast<KeyType*>(toNative(wrapper)) == key); - v8::Persistent<v8::Object> persistent(m_isolate, wrapper); - configuration.configureWrapper(&persistent); - persistent.SetWeak(this, &setWeakCallback); - typename MapType::AddResult result = m_map.add(key, UnsafePersistent<v8::Object>()); - ASSERT(result.isNewEntry); - // FIXME: Stop handling this case once duplicate wrappers are guaranteed not to be created. - if (!result.isNewEntry) - result.iterator->value.dispose(); - result.iterator->value = UnsafePersistent<v8::Object>(persistent); + RELEASE_ASSERT(!containsKey(key)); // See crbug.com/368095 + v8::UniquePersistent<v8::Object> unique(m_isolate, wrapper); + configuration.configureWrapper(&unique); + m_map.Set(key, unique.Pass()); } void clear() { - while (!m_map.isEmpty()) { - // Swap out m_map on each iteration to ensure any wrappers added due to side effects of the loop are cleared. - MapType map; - map.swap(m_map); - for (typename MapType::iterator it = map.begin(); it != map.end(); ++it) { - toWrapperTypeInfo(*(it->value.persistent()))->derefObject(it->key); - it->value.dispose(); - } - } + m_map.Clear(); } void removeAndDispose(KeyType* key) { - typename MapType::iterator it = m_map.find(key); - ASSERT_WITH_SECURITY_IMPLICATION(it != m_map.end()); - it->value.dispose(); - m_map.remove(it); + ASSERT(containsKey(key)); + m_map.Remove(key); } private: - static void setWeakCallback(const v8::WeakCallbackData<v8::Object, DOMWrapperMap<KeyType> >&); + class PersistentValueMapTraits { + public: + // Map traits: + typedef HashMap<KeyType*, v8::PersistentContainerValue> Impl; + typedef typename Impl::iterator Iterator; + static size_t Size(const Impl* impl) { return impl->size(); } + static bool Empty(Impl* impl) { return impl->isEmpty(); } + static void Swap(Impl& impl, Impl& other) { impl.swap(other); } + static Iterator Begin(Impl* impl) { return impl->begin(); } + static Iterator End(Impl* impl) { return impl->end(); } + static v8::PersistentContainerValue Value(Iterator& iter) + { + return iter->value; + } + static KeyType* Key(Iterator& iter) { return iter->key; } + static v8::PersistentContainerValue Set( + Impl* impl, KeyType* key, v8::PersistentContainerValue value) + { + v8::PersistentContainerValue oldValue = Get(impl, key); + impl->set(key, value); + return oldValue; + } + static v8::PersistentContainerValue Get(const Impl* impl, KeyType* key) + { + return impl->get(key); + } + + static v8::PersistentContainerValue Remove(Impl* impl, KeyType* key) + { + return impl->take(key); + } + + // Weak traits: + static const v8::PersistentContainerCallbackType kCallbackType = v8::kWeak; + typedef v8::PersistentValueMap<KeyType*, v8::Object, PersistentValueMapTraits> MapType; + typedef MapType WeakCallbackDataType; + + static WeakCallbackDataType* WeakCallbackParameter(MapType* map, KeyType* key, v8::Local<v8::Object>& value) + { + return map; + } + + static void DisposeCallbackData(WeakCallbackDataType* callbackData) { } + + static MapType* MapFromWeakCallbackData( + const v8::WeakCallbackData<v8::Object, WeakCallbackDataType>& data) + { + return data.GetParameter(); + } + + static KeyType* KeyFromWeakCallbackData( + const v8::WeakCallbackData<v8::Object, WeakCallbackDataType>& data) + { + return static_cast<KeyType*>(toNative(data.GetValue())); + } + + // Dispose traits: + // Generally nothing to do, but see below for a specialization for + // DomWrapperMap<void>. + static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<v8::Object> value, KeyType* key) { } + }; v8::Isolate* m_isolate; - MapType m_map; + typename PersistentValueMapTraits::MapType m_map; }; -template<> -inline void DOMWrapperMap<void>::setWeakCallback(const v8::WeakCallbackData<v8::Object, DOMWrapperMap<void> >& data) +template <> +inline void DOMWrapperMap<void>::PersistentValueMapTraits::Dispose( + v8::Isolate* isolate, + v8::UniquePersistent<v8::Object> value, + void* key) { - const WrapperTypeInfo* type = toWrapperTypeInfo(data.GetValue()); - ASSERT(type->derefObjectFunction); - void* key = static_cast<void*>(toNative(data.GetValue())); - ASSERT(*(data.GetParameter()->m_map.get(key).persistent()) == data.GetValue()); - data.GetParameter()->removeAndDispose(key); - type->derefObject(key); + RELEASE_ASSERT(!value.IsEmpty()); // See crbug.com/368095. + releaseObject(v8::Local<v8::Object>::New(isolate, value)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.cpp b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.cpp index d014206817f..59cb4505716 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "bindings/v8/DOMWrapperWorld.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/DOMDataStore.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" @@ -41,70 +41,30 @@ #include "bindings/v8/WrapperTypeInfo.h" #include "core/dom/ExecutionContext.h" #include "wtf/HashTraits.h" -#include "wtf/MainThread.h" #include "wtf/StdLibExtras.h" namespace WebCore { unsigned DOMWrapperWorld::isolatedWorldCount = 0; -static bool initializingWindow = false; +DOMWrapperWorld* DOMWrapperWorld::worldOfInitializingWindow = 0; -void DOMWrapperWorld::setInitializingWindow(bool initializing) +PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::create(int worldId, int extensionGroup) { - initializingWindow = initializing; -} - -PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::createMainWorld() -{ - return adoptRef(new DOMWrapperWorld(MainWorldId, mainWorldExtensionGroup)); + return adoptRef(new DOMWrapperWorld(worldId, extensionGroup)); } DOMWrapperWorld::DOMWrapperWorld(int worldId, int extensionGroup) : m_worldId(worldId) , m_extensionGroup(extensionGroup) + , m_domDataStore(adoptPtr(new DOMDataStore(isMainWorld()))) { - if (isIsolatedWorld()) - m_domDataStore = adoptPtr(new DOMDataStore(IsolatedWorld)); -} - -DOMWrapperWorld* DOMWrapperWorld::current() -{ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); - v8::Handle<v8::Context> context = isolate->GetCurrentContext(); - if (!V8DOMWrapper::isWrapperOfType(toInnerGlobalObject(context), &V8Window::wrapperTypeInfo)) - return 0; - ASSERT(isMainThread()); - if (DOMWrapperWorld* world = isolatedWorld(context)) - return world; - return mainThreadNormalWorld(); } -DOMWrapperWorld* mainThreadNormalWorld() +DOMWrapperWorld& DOMWrapperWorld::mainWorld() { ASSERT(isMainThread()); - DEFINE_STATIC_REF(DOMWrapperWorld, cachedNormalWorld, (DOMWrapperWorld::createMainWorld())); - return cachedNormalWorld; -} - -// FIXME: Remove this function. There is currently an issue with the inspector related to the call to dispatchDidClearWindowObjectInWorld in ScriptController::windowShell. -DOMWrapperWorld* existingWindowShellWorkaroundWorld() -{ - DEFINE_STATIC_REF(DOMWrapperWorld, world, (adoptRef(new DOMWrapperWorld(MainWorldId - 1, DOMWrapperWorld::mainWorldExtensionGroup - 1)))); - return world; -} - -bool DOMWrapperWorld::contextHasCorrectPrototype(v8::Handle<v8::Context> context) -{ - ASSERT(isMainThread()); - if (initializingWindow) - return true; - return V8DOMWrapper::isWrapperOfType(toInnerGlobalObject(context), &V8Window::wrapperTypeInfo); -} - -void DOMWrapperWorld::setIsolatedWorldField(v8::Handle<v8::Context> context) -{ - V8PerContextDataHolder::from(context)->setIsolatedWorld(isMainWorld() ? 0 : this); + DEFINE_STATIC_REF(DOMWrapperWorld, cachedMainWorld, (DOMWrapperWorld::create(MainWorldId, mainWorldExtensionGroup))); + return *cachedMainWorld; } typedef HashMap<int, DOMWrapperWorld*> WorldMap; @@ -115,9 +75,10 @@ static WorldMap& isolatedWorldMap() return map; } -void DOMWrapperWorld::getAllWorlds(Vector<RefPtr<DOMWrapperWorld> >& worlds) +void DOMWrapperWorld::allWorldsInMainThread(Vector<RefPtr<DOMWrapperWorld> >& worlds) { - worlds.append(mainThreadNormalWorld()); + ASSERT(isMainThread()); + worlds.append(&mainWorld()); WorldMap& isolatedWorlds = isolatedWorldMap(); for (WorldMap::iterator it = isolatedWorlds.begin(); it != isolatedWorlds.end(); ++it) worlds.append(it->value); @@ -127,48 +88,57 @@ DOMWrapperWorld::~DOMWrapperWorld() { ASSERT(!isMainWorld()); + dispose(); + if (!isIsolatedWorld()) return; WorldMap& map = isolatedWorldMap(); - WorldMap::iterator i = map.find(m_worldId); - if (i == map.end()) { + WorldMap::iterator it = map.find(m_worldId); + if (it == map.end()) { ASSERT_NOT_REACHED(); return; } - ASSERT(i->value == this); + ASSERT(it->value == this); - map.remove(i); + map.remove(it); isolatedWorldCount--; ASSERT(map.size() == isolatedWorldCount); } +void DOMWrapperWorld::dispose() +{ + m_domDataStore.clear(); +} + +#ifndef NDEBUG +static bool isIsolatedWorldId(int worldId) +{ + return MainWorldId < worldId && worldId < IsolatedWorldIdLimit; +} +#endif + PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::ensureIsolatedWorld(int worldId, int extensionGroup) { - ASSERT(worldId > MainWorldId); + ASSERT(isIsolatedWorldId(worldId)); WorldMap& map = isolatedWorldMap(); WorldMap::AddResult result = map.add(worldId, 0); - RefPtr<DOMWrapperWorld> world = result.iterator->value; + RefPtr<DOMWrapperWorld> world = result.storedValue->value; if (world) { ASSERT(world->worldId() == worldId); ASSERT(world->extensionGroup() == extensionGroup); return world.release(); } - world = adoptRef(new DOMWrapperWorld(worldId, extensionGroup)); - result.iterator->value = world.get(); + world = DOMWrapperWorld::create(worldId, extensionGroup); + result.storedValue->value = world.get(); isolatedWorldCount++; ASSERT(map.size() == isolatedWorldCount); return world.release(); } -v8::Handle<v8::Context> DOMWrapperWorld::context(ScriptController& controller) -{ - return controller.windowShell(this)->context(); -} - typedef HashMap<int, RefPtr<SecurityOrigin> > IsolatedWorldSecurityOriginMap; static IsolatedWorldSecurityOriginMap& isolatedWorldSecurityOrigins() { @@ -185,19 +155,13 @@ SecurityOrigin* DOMWrapperWorld::isolatedWorldSecurityOrigin() return it == origins.end() ? 0 : it->value.get(); } -void DOMWrapperWorld::setIsolatedWorldSecurityOrigin(int worldID, PassRefPtr<SecurityOrigin> securityOrigin) +void DOMWrapperWorld::setIsolatedWorldSecurityOrigin(int worldId, PassRefPtr<SecurityOrigin> securityOrigin) { - ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); + ASSERT(isIsolatedWorldId(worldId)); if (securityOrigin) - isolatedWorldSecurityOrigins().set(worldID, securityOrigin); + isolatedWorldSecurityOrigins().set(worldId, securityOrigin); else - isolatedWorldSecurityOrigins().remove(worldID); -} - -void DOMWrapperWorld::clearIsolatedWorldSecurityOrigin(int worldID) -{ - ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); - isolatedWorldSecurityOrigins().remove(worldID); + isolatedWorldSecurityOrigins().remove(worldId); } typedef HashMap<int, bool> IsolatedWorldContentSecurityPolicyMap; @@ -216,39 +180,13 @@ bool DOMWrapperWorld::isolatedWorldHasContentSecurityPolicy() return it == policies.end() ? false : it->value; } -void DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(int worldID, const String& policy) +void DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(int worldId, const String& policy) { - ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); + ASSERT(isIsolatedWorldId(worldId)); if (!policy.isEmpty()) - isolatedWorldContentSecurityPolicies().set(worldID, true); + isolatedWorldContentSecurityPolicies().set(worldId, true); else - isolatedWorldContentSecurityPolicies().remove(worldID); -} - -void DOMWrapperWorld::clearIsolatedWorldContentSecurityPolicy(int worldID) -{ - ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); - isolatedWorldContentSecurityPolicies().remove(worldID); -} - -typedef HashMap<int, OwnPtr<V8DOMActivityLogger>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int> > DOMActivityLoggerMap; -static DOMActivityLoggerMap& domActivityLoggers() -{ - ASSERT(isMainThread()); - DEFINE_STATIC_LOCAL(DOMActivityLoggerMap, map, ()); - return map; -} - -void DOMWrapperWorld::setActivityLogger(int worldId, PassOwnPtr<V8DOMActivityLogger> logger) -{ - domActivityLoggers().set(worldId, logger); -} - -V8DOMActivityLogger* DOMWrapperWorld::activityLogger(int worldId) -{ - DOMActivityLoggerMap& loggers = domActivityLoggers(); - DOMActivityLoggerMap::iterator it = loggers.find(worldId); - return it == loggers.end() ? 0 : it->value.get(); + isolatedWorldContentSecurityPolicies().remove(worldId); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.h b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.h index 201e019309f..aa294a1fcfb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.h @@ -31,54 +31,67 @@ #ifndef DOMWrapperWorld_h #define DOMWrapperWorld_h -#include "bindings/v8/V8DOMActivityLogger.h" -#include "bindings/v8/V8PerContextData.h" +#include "bindings/v8/ScriptState.h" #include "platform/weborigin/SecurityOrigin.h" -#include <v8.h> +#include "wtf/MainThread.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" +#include <v8.h> namespace WebCore { class DOMDataStore; -class ScriptController; class ExecutionContext; +class ScriptController; enum WorldIdConstants { MainWorldId = 0, + // Embedder isolated worlds can use IDs in [1, 1<<29). EmbedderWorldIdLimit = (1 << 29), - ScriptPreprocessorIsolatedWorldId + ScriptPreprocessorIsolatedWorldId, + IsolatedWorldIdLimit, + WorkerWorldId, + TestingWorldId, }; // This class represent a collection of DOM wrappers for a specific world. class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { public: + static PassRefPtr<DOMWrapperWorld> create(int worldId = -1, int extensionGroup = -1); + static const int mainWorldExtensionGroup = 0; static PassRefPtr<DOMWrapperWorld> ensureIsolatedWorld(int worldId, int extensionGroup); ~DOMWrapperWorld(); + void dispose(); static bool isolatedWorldsExist() { return isolatedWorldCount; } - static bool isIsolatedWorldId(int worldId) { return worldId > MainWorldId; } - static void getAllWorlds(Vector<RefPtr<DOMWrapperWorld> >& worlds); + static void allWorldsInMainThread(Vector<RefPtr<DOMWrapperWorld> >& worlds); - void setIsolatedWorldField(v8::Handle<v8::Context>); + static DOMWrapperWorld& world(v8::Handle<v8::Context> context) + { + return ScriptState::from(context)->world(); + } - static DOMWrapperWorld* isolatedWorld(v8::Handle<v8::Context> context) + static DOMWrapperWorld& current(v8::Isolate* isolate) { - ASSERT(contextHasCorrectPrototype(context)); - return V8PerContextDataHolder::from(context)->isolatedWorld(); + if (isMainThread() && worldOfInitializingWindow) { + // It's possible that current() is being called while window is being initialized. + // In order to make current() workable during the initialization phase, + // we cache the world of the initializing window on worldOfInitializingWindow. + // If there is no initiazing window, worldOfInitializingWindow is 0. + return *worldOfInitializingWindow; + } + return world(isolate->GetCurrentContext()); } - // Will return null if there is no DOMWrapperWorld for the current v8::Context - static DOMWrapperWorld* current(); + static DOMWrapperWorld& mainWorld(); // Associates an isolated world (see above for description) with a security // origin. XMLHttpRequest instances used in that world will be considered // to come from that origin, not the frame's. - static void setIsolatedWorldSecurityOrigin(int worldID, PassRefPtr<SecurityOrigin>); - static void clearIsolatedWorldSecurityOrigin(int worldID); + static void setIsolatedWorldSecurityOrigin(int worldId, PassRefPtr<SecurityOrigin>); SecurityOrigin* isolatedWorldSecurityOrigin(); // Associated an isolated world with a Content Security Policy. Resources @@ -89,50 +102,36 @@ public: // FIXME: Right now, resource injection simply bypasses the main world's // DOM. More work is necessary to allow the isolated world's policy to be // applied correctly. - static void setIsolatedWorldContentSecurityPolicy(int worldID, const String& policy); - static void clearIsolatedWorldContentSecurityPolicy(int worldID); + static void setIsolatedWorldContentSecurityPolicy(int worldId, const String& policy); bool isolatedWorldHasContentSecurityPolicy(); - // Associate a logger with the world identified by worldId (worlId may be 0 - // identifying the main world). - static void setActivityLogger(int worldId, PassOwnPtr<V8DOMActivityLogger>); - static V8DOMActivityLogger* activityLogger(int worldId); - bool isMainWorld() const { return m_worldId == MainWorldId; } - bool isIsolatedWorld() const { return isIsolatedWorldId(m_worldId); } + bool isWorkerWorld() const { return m_worldId == WorkerWorldId; } + bool isIsolatedWorld() const { return MainWorldId < m_worldId && m_worldId < IsolatedWorldIdLimit; } int worldId() const { return m_worldId; } int extensionGroup() const { return m_extensionGroup; } - DOMDataStore& isolatedWorldDOMDataStore() const + DOMDataStore& domDataStore() const { return *m_domDataStore; } + + static void setWorldOfInitializingWindow(DOMWrapperWorld* world) { - ASSERT(isIsolatedWorld()); - return *m_domDataStore; + ASSERT(isMainThread()); + worldOfInitializingWindow = world; } - v8::Handle<v8::Context> context(ScriptController&); - - static void setInitializingWindow(bool); + // FIXME: Remove this method once we fix crbug.com/345014. + static bool windowIsBeingInitialized() { return !!worldOfInitializingWindow; } private: - static unsigned isolatedWorldCount; - static PassRefPtr<DOMWrapperWorld> createMainWorld(); - static bool contextHasCorrectPrototype(v8::Handle<v8::Context>); - DOMWrapperWorld(int worldId, int extensionGroup); + static unsigned isolatedWorldCount; + static DOMWrapperWorld* worldOfInitializingWindow; + const int m_worldId; const int m_extensionGroup; OwnPtr<DOMDataStore> m_domDataStore; - - friend DOMWrapperWorld* mainThreadNormalWorld(); - friend DOMWrapperWorld* existingWindowShellWorkaroundWorld(); }; -DOMWrapperWorld* mainThreadNormalWorld(); - -// FIXME: this is a workaround for a problem in ScriptController -// Do not use this anywhere else!! -DOMWrapperWorld* existingWindowShellWorkaroundWorld(); - } // namespace WebCore #endif // DOMWrapperWorld_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DebuggerScript.js b/chromium/third_party/WebKit/Source/bindings/v8/DebuggerScript.js index 2f92b48013e..bec40048c12 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DebuggerScript.js +++ b/chromium/third_party/WebKit/Source/bindings/v8/DebuggerScript.js @@ -33,11 +33,17 @@ var DebuggerScript = {}; DebuggerScript.PauseOnExceptionsState = { - DontPauseOnExceptions : 0, - PauseOnAllExceptions : 1, + DontPauseOnExceptions: 0, + PauseOnAllExceptions: 1, PauseOnUncaughtExceptions: 2 }; +DebuggerScript.ScopeInfoDetails = { + AllScopes: 0, + FastAsyncScopes: 1, + NoScopes: 2 +}; + DebuggerScript._pauseOnExceptionsState = DebuggerScript.PauseOnExceptionsState.DontPauseOnExceptions; Debug.clearBreakOnException(); Debug.clearBreakOnUncaughtException(); @@ -70,10 +76,10 @@ DebuggerScript.getFunctionScopes = function(fun) return null; var result = []; for (var i = 0; i < count; i++) { - var scopeMirror = mirror.scope(i); + var scopeDetails = mirror.scope(i).details(); result[i] = { - type: scopeMirror.scopeType(), - object: DebuggerScript._buildScopeObject(scopeMirror) + type: scopeDetails.type(), + object: DebuggerScript._buildScopeObject(scopeDetails.type(), scopeDetails.object()) }; } return result; @@ -199,15 +205,23 @@ DebuggerScript.setPauseOnExceptionsState = function(newState) Debug.clearBreakOnUncaughtException(); } -DebuggerScript.currentCallFrame = function(execState, maximumLimit) +DebuggerScript.frameCount = function(execState) { + return execState.frameCount(); +} + +DebuggerScript.currentCallFrame = function(execState, data) +{ + var maximumLimit = data >> 2; + var scopeDetailsLevel = data & 3; + var frameCount = execState.frameCount(); - if (maximumLimit >= 0 && maximumLimit < frameCount) + if (maximumLimit && maximumLimit < frameCount) frameCount = maximumLimit; var topFrame = undefined; for (var i = frameCount - 1; i >= 0; i--) { var frameMirror = execState.frame(i); - topFrame = DebuggerScript._frameMirrorToJSCallFrame(frameMirror, topFrame); + topFrame = DebuggerScript._frameMirrorToJSCallFrame(frameMirror, topFrame, scopeDetailsLevel); } return topFrame; } @@ -219,14 +233,12 @@ DebuggerScript.stepIntoStatement = function(execState) DebuggerScript.stepOverStatement = function(execState, callFrame) { - var frameMirror = callFrame ? callFrame.frameMirror : undefined; - execState.prepareStep(Debug.StepAction.StepNext, 1, frameMirror); + execState.prepareStep(Debug.StepAction.StepNext, 1); } DebuggerScript.stepOutOfFunction = function(execState, callFrame) { - var frameMirror = callFrame ? callFrame.frameMirror : undefined; - execState.prepareStep(Debug.StepAction.StepOut, 1, frameMirror); + execState.prepareStep(Debug.StepAction.StepOut, 1); } // Returns array in form: @@ -310,43 +322,95 @@ DebuggerScript.isEvalCompilation = function(eventData) return (script.compilationType() === Debug.ScriptCompilationType.Eval); } -DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame) +// NOTE: This function is performance critical, as it can be run on every +// statement that generates an async event (like addEventListener) to support +// asynchronous call stacks. Thus, when possible, initialize the data lazily. +DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame, scopeDetailsLevel) { - // Get function name and display name. + // Stuff that can not be initialized lazily (i.e. valid while paused with a valid break_id). + // The frameMirror and scopeMirror can be accessed only while paused on the debugger. + var frameDetails = frameMirror.details(); + + var funcObject = frameDetails.func(); + var sourcePosition = frameDetails.sourcePosition(); + var thisObject = frameDetails.receiver(); + + var isAtReturn = !!frameDetails.isAtReturn(); + var returnValue = isAtReturn ? frameDetails.returnValue() : undefined; + + var scopeMirrors = (scopeDetailsLevel === DebuggerScript.ScopeInfoDetails.NoScopes ? [] : frameMirror.allScopes(scopeDetailsLevel === DebuggerScript.ScopeInfoDetails.FastAsyncScopes)); + var scopeTypes = new Array(scopeMirrors.length); + var scopeObjects = new Array(scopeMirrors.length); + for (var i = 0; i < scopeMirrors.length; ++i) { + var scopeDetails = scopeMirrors[i].details(); + scopeTypes[i] = scopeDetails.type(); + scopeObjects[i] = scopeDetails.object(); + } + + // Calculated lazily. + var scopeChain; var funcMirror; - var displayName; - try { - funcMirror = frameMirror.func(); - if (funcMirror) { - var valueMirror = funcMirror.property("displayName").value(); - if (valueMirror && valueMirror.isString()) - displayName = valueMirror.value(); + var location; + + function lazyScopeChain() + { + if (!scopeChain) { + scopeChain = []; + for (var i = 0; i < scopeObjects.length; ++i) + scopeChain.push(DebuggerScript._buildScopeObject(scopeTypes[i], scopeObjects[i])); + scopeObjects = null; // Free for GC. + } + return scopeChain; + } + + function ensureFuncMirror() + { + if (!funcMirror) { + funcMirror = MakeMirror(funcObject); + if (!funcMirror.isFunction()) + funcMirror = new UnresolvedFunctionMirror(funcObject); } - } catch(e) { + return funcMirror; } - var functionName; - if (funcMirror) - functionName = displayName || funcMirror.name() || funcMirror.inferredName(); - // Get script ID. - var script = funcMirror.script(); - var sourceID = script && script.id(); + function ensureLocation() + { + if (!location) { + var script = ensureFuncMirror().script(); + if (script) + location = script.locationFromPosition(sourcePosition, true); + if (!location) + location = { line: 0, column: 0 }; + } + return location; + } - // Get location. - var location = frameMirror.sourceLocation(); + function line() + { + return ensureLocation().line; + } - // Get this object. - var thisObject = frameMirror.details_.receiver(); + function column() + { + return ensureLocation().column; + } - var isAtReturn = !!frameMirror.details_.isAtReturn(); - var returnValue = isAtReturn ? frameMirror.details_.returnValue() : undefined; + function sourceID() + { + var script = ensureFuncMirror().script(); + return script && script.id(); + } - var scopeChain = []; - var scopeType = []; - for (var i = 0; i < frameMirror.scopeCount(); i++) { - var scopeMirror = frameMirror.scope(i); - scopeType.push(scopeMirror.scopeType()); - scopeChain.push(DebuggerScript._buildScopeObject(scopeMirror)); + function functionName() + { + var func = ensureFuncMirror(); + if (!func.resolved()) + return undefined; + var displayName; + var valueMirror = func.property("displayName").value(); + if (valueMirror && valueMirror.isString()) + displayName = valueMirror.value(); + return displayName || func.name() || func.inferredName(); } function evaluate(expression) @@ -370,7 +434,7 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame) var stepInPositionsProtocol; if (stepInPositionsV8) { stepInPositionsProtocol = []; - var script = frameMirror.func().script(); + var script = ensureFuncMirror().script(); if (script) { var scriptId = String(script.id()); for (var i = 0; i < stepInPositionsV8.length; i++) { @@ -388,54 +452,55 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame) return { "sourceID": sourceID, - "line": location ? location.line : 0, - "column": location ? location.column : 0, + "line": line, + "column": column, "functionName": functionName, "thisObject": thisObject, - "scopeChain": scopeChain, - "scopeType": scopeType, + "scopeChain": lazyScopeChain, + "scopeType": scopeTypes, "evaluate": evaluate, "caller": callerFrame, "restart": restart, "setVariableValue": setVariableValue, "stepInPositions": stepInPositions, "isAtReturn": isAtReturn, - "returnValue": returnValue, - "frameMirror": frameMirror + "returnValue": returnValue }; } -DebuggerScript._buildScopeObject = function(scopeMirror) { - var scopeObject; - switch (scopeMirror.scopeType()) { +DebuggerScript._buildScopeObject = function(scopeType, scopeObject) +{ + var result; + switch (scopeType) { case ScopeType.Local: case ScopeType.Closure: case ScopeType.Catch: // For transient objects we create a "persistent" copy that contains // the same properties. - scopeObject = {}; // Reset scope object prototype to null so that the proto properties // don't appear in the local scope section. - scopeObject.__proto__ = null; - var scopeObjectMirror = scopeMirror.scopeObject(); - var properties = scopeObjectMirror.properties(); + result = { __proto__: null }; + var properties = MakeMirror(scopeObject, true /* transient */).properties(); for (var j = 0; j < properties.length; j++) { var name = properties[j].name(); if (name.charAt(0) === ".") continue; // Skip internal variables like ".arguments" - scopeObject[name] = properties[j].value_; + result[name] = properties[j].value_; } break; case ScopeType.Global: case ScopeType.With: - scopeObject = scopeMirror.details_.object(); + result = scopeObject; break; case ScopeType.Block: // Unsupported yet. Mustn't be reachable. break; } - return scopeObject; + return result; } +// We never resolve Mirror by its handle so to avoid memory leaks caused by Mirrors in the cache we disable it. +ToggleMirrorCache(false); + return DebuggerScript; })(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.cpp b/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.cpp index 6431d5b1738..156eede687c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.cpp @@ -26,36 +26,35 @@ #include "config.h" #include "bindings/v8/Dictionary.h" -#include "V8DOMError.h" -#include "V8EventTarget.h" -#include "V8IDBKeyRange.h" -#include "V8MIDIPort.h" -#include "V8MediaKeyError.h" -#include "V8SpeechRecognitionError.h" -#include "V8SpeechRecognitionResult.h" -#include "V8SpeechRecognitionResultList.h" -#include "V8Storage.h" -#include "V8VoidCallback.h" -#include "V8Window.h" +#include "bindings/core/v8/V8DOMError.h" +#include "bindings/core/v8/V8EventTarget.h" +#include "bindings/core/v8/V8MediaKeyError.h" +#include "bindings/core/v8/V8MessagePort.h" +#include "bindings/core/v8/V8Storage.h" +#include "bindings/core/v8/V8TextTrack.h" +#include "bindings/core/v8/V8VoidCallback.h" +#include "bindings/core/v8/V8Window.h" +#include "bindings/modules/v8/V8Gamepad.h" +#include "bindings/modules/v8/V8HeaderMap.h" +#include "bindings/modules/v8/V8IDBKeyRange.h" +#include "bindings/modules/v8/V8MIDIPort.h" +#include "bindings/modules/v8/V8MediaStream.h" +#include "bindings/modules/v8/V8SpeechRecognitionResult.h" +#include "bindings/modules/v8/V8SpeechRecognitionResultList.h" #include "bindings/v8/ArrayValue.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "bindings/v8/custom/V8Uint8ArrayCustom.h" +#include "core/html/track/TrackBase.h" +#include "modules/gamepad/Gamepad.h" #include "modules/indexeddb/IDBKeyRange.h" -#include "modules/speech/SpeechRecognitionError.h" +#include "modules/mediastream/MediaStream.h" #include "modules/speech/SpeechRecognitionResult.h" #include "modules/speech/SpeechRecognitionResultList.h" #include "wtf/MathExtras.h" -#include "V8TextTrack.h" -#include "core/html/track/TrackBase.h" - -#include "V8MediaStream.h" -#include "modules/mediastream/MediaStream.h" - namespace WebCore { Dictionary::Dictionary() @@ -174,7 +173,7 @@ bool Dictionary::get(const String& key, double& value, bool& hasValue) const } hasValue = true; - V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); + TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); if (v8Number.IsEmpty()) return false; value = v8Number->Value(); @@ -199,17 +198,28 @@ bool Dictionary::convert(ConversionContext& context, const String& key, double& return true; } -bool Dictionary::get(const String& key, String& value) const +template<typename StringType> +inline bool Dictionary::getStringType(const String& key, StringType& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false); value = stringValue; return true; } +bool Dictionary::get(const String& key, String& value) const +{ + return getStringType(key, value); +} + +bool Dictionary::get(const String& key, AtomicString& value) const +{ + return getStringType(key, value); +} + bool Dictionary::convert(ConversionContext& context, const String& key, String& value) const { ConversionContextScope scope(context); @@ -218,7 +228,7 @@ bool Dictionary::convert(ConversionContext& context, const String& key, String& if (!getKey(key, v8Value)) return true; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false); value = stringValue; return true; } @@ -229,7 +239,7 @@ bool Dictionary::get(const String& key, ScriptValue& value) const if (!getKey(key, v8Value)) return false; - value = ScriptValue(v8Value, m_isolate); + value = ScriptValue(ScriptState::current(m_isolate), v8Value); return true; } @@ -299,7 +309,7 @@ bool Dictionary::get(const String& key, unsigned long long& value) const if (!getKey(key, v8Value)) return false; - V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); + TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); if (v8Number.IsEmpty()) return false; double d = v8Number->Value(); @@ -307,7 +317,7 @@ bool Dictionary::get(const String& key, unsigned long long& value) const return true; } -bool Dictionary::get(const String& key, RefPtr<DOMWindow>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<LocalDOMWindow>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) @@ -315,25 +325,17 @@ bool Dictionary::get(const String& key, RefPtr<DOMWindow>& value) const // We need to handle a DOMWindow specially, because a DOMWindow wrapper // exists on a prototype chain of v8Value. - value = 0; - if (v8Value->IsObject()) { - v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); - v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate))); - if (!window.IsEmpty()) - value = V8Window::toNative(window); - } + value = toDOMWindow(v8Value, m_isolate); return true; } -bool Dictionary::get(const String& key, RefPtr<Storage>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<Storage>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - if (V8Storage::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8Storage::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8Storage::toNativeWithTypeCheck(m_isolate, v8Value); return true; } @@ -345,7 +347,11 @@ bool Dictionary::get(const String& key, MessagePortArray& value) const ASSERT(m_isolate); ASSERT(m_isolate == v8::Isolate::GetCurrent()); - return getMessagePortArray(v8Value, key, value, m_isolate); + if (WebCore::isUndefinedOrNull(v8Value)) + return true; + bool success = false; + value = toRefPtrNativeArray<MessagePort, V8MessagePort>(v8Value, key, m_isolate, &success); + return success; } bool Dictionary::convert(ConversionContext& context, const String& key, MessagePortArray& value) const @@ -373,8 +379,8 @@ bool Dictionary::get(const String& key, HashSet<AtomicString>& value) const ASSERT(m_isolate == v8::Isolate::GetCurrent()); v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value); for (size_t i = 0; i < v8Array->Length(); ++i) { - v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(i, m_isolate)); - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, indexedValue, false); + v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(m_isolate, i)); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, indexedValue, false); value.add(stringValue); } @@ -406,7 +412,7 @@ bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) c if (!getKey(key, v8Value) || WebCore::isUndefinedOrNull(v8Value)) return false; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false); value = stringValue; return true; } @@ -417,9 +423,7 @@ bool Dictionary::get(const String& key, RefPtr<Uint8Array>& value) const if (!getKey(key, v8Value)) return false; - value = 0; - if (V8Uint8Array::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8Uint8Array::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8Uint8Array::toNativeWithTypeCheck(m_isolate, v8Value); return true; } @@ -429,21 +433,17 @@ bool Dictionary::get(const String& key, RefPtr<ArrayBufferView>& value) const if (!getKey(key, v8Value)) return false; - value = 0; - if (V8ArrayBufferView::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8ArrayBufferView::toNativeWithTypeCheck(m_isolate, v8Value); return true; } -bool Dictionary::get(const String& key, RefPtr<MIDIPort>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<MIDIPort>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - if (V8MIDIPort::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8MIDIPort::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8MIDIPort::toNativeWithTypeCheck(m_isolate, v8Value); return true; } @@ -453,13 +453,11 @@ bool Dictionary::get(const String& key, RefPtr<MediaKeyError>& value) const if (!getKey(key, v8Value)) return false; - value = 0; - if (V8MediaKeyError::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8MediaKeyError::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8MediaKeyError::toNativeWithTypeCheck(m_isolate, v8Value); return true; } -bool Dictionary::get(const String& key, RefPtr<TrackBase>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<TrackBase>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) @@ -471,7 +469,7 @@ bool Dictionary::get(const String& key, RefPtr<TrackBase>& value) const // FIXME: this will need to be changed so it can also return an AudioTrack or a VideoTrack once // we add them. - v8::Handle<v8::Object> track = wrapper->FindInstanceInPrototypeChain(V8TextTrack::domTemplate(m_isolate, worldType(m_isolate))); + v8::Handle<v8::Object> track = V8TextTrack::findInstanceInPrototypeChain(wrapper, m_isolate); if (!track.IsEmpty()) source = V8TextTrack::toNative(track); } @@ -479,39 +477,33 @@ bool Dictionary::get(const String& key, RefPtr<TrackBase>& value) const return true; } -bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionError>& value) const +bool Dictionary::get(const String& key, Member<SpeechRecognitionResult>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - if (V8SpeechRecognitionError::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8SpeechRecognitionError::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8SpeechRecognitionResult::toNativeWithTypeCheck(m_isolate, v8Value); return true; } -bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResult>& value) const +bool Dictionary::get(const String& key, Member<SpeechRecognitionResultList>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - if (V8SpeechRecognitionResult::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8SpeechRecognitionResult::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8SpeechRecognitionResultList::toNativeWithTypeCheck(m_isolate, v8Value); return true; } -bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResultList>& value) const +bool Dictionary::get(const String& key, Member<Gamepad>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - if (V8SpeechRecognitionResultList::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8SpeechRecognitionResultList::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8Gamepad::toNativeWithTypeCheck(m_isolate, v8Value); return true; } @@ -521,24 +513,22 @@ bool Dictionary::get(const String& key, RefPtr<MediaStream>& value) const if (!getKey(key, v8Value)) return false; - value = 0; - if (V8MediaStream::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8MediaStream::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8MediaStream::toNativeWithTypeCheck(m_isolate, v8Value); return true; } -bool Dictionary::get(const String& key, RefPtr<EventTarget>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<EventTarget>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - // We need to handle a DOMWindow specially, because a DOMWindow wrapper + value = nullptr; + // We need to handle a LocalDOMWindow specially, because a LocalDOMWindow wrapper // exists on a prototype chain of v8Value. if (v8Value->IsObject()) { v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); - v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate))); + v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(wrapper, m_isolate); if (!window.IsEmpty()) { value = toWrapperTypeInfo(window)->toEventTarget(window); return true; @@ -567,6 +557,16 @@ bool Dictionary::get(const String& key, Dictionary& value) const return true; } +bool Dictionary::get(const String& key, RefPtr<HeaderMap>& value) const +{ + v8::Local<v8::Value> v8Value; + if (!getKey(key, v8Value)) + return false; + + value = V8HeaderMap::toNativeWithTypeCheck(m_isolate, v8Value); + return true; +} + bool Dictionary::convert(ConversionContext& context, const String& key, Dictionary& value) const { ConversionContextScope scope(context); @@ -596,8 +596,8 @@ bool Dictionary::get(const String& key, Vector<String>& value) const v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value); for (size_t i = 0; i < v8Array->Length(); ++i) { - v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Uint32::New(i, m_isolate)); - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, indexedValue, false); + v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Uint32::New(m_isolate, i)); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, indexedValue, false); value.append(stringValue); } @@ -657,33 +657,13 @@ bool Dictionary::convert(ConversionContext& context, const String& key, ArrayVal return get(key, value); } -bool Dictionary::get(const String& key, RefPtr<DOMError>& value) const -{ - v8::Local<v8::Value> v8Value; - if (!getKey(key, v8Value)) - return false; - - DOMError* error = 0; - if (v8Value->IsObject()) { - v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); - v8::Handle<v8::Object> domError = wrapper->FindInstanceInPrototypeChain(V8DOMError::domTemplate(m_isolate, worldType(m_isolate))); - if (!domError.IsEmpty()) - error = V8DOMError::toNative(domError); - } - value = error; - return true; -} - -bool Dictionary::get(const String& key, OwnPtr<VoidCallback>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<DOMError>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - if (!v8Value->IsFunction()) - return false; - - value = V8VoidCallback::create(v8::Handle<v8::Function>::Cast(v8Value), getExecutionContext()); + value = V8DOMError::toNativeWithTypeCheck(m_isolate, v8Value); return true; } @@ -705,8 +685,8 @@ bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMa continue; v8::Local<v8::Value> value = options->Get(key); - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringKey, key, false); - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, value, false); + TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, false); if (!static_cast<const String&>(stringKey).isEmpty()) hashMap.set(stringKey, stringValue); } @@ -730,7 +710,7 @@ bool Dictionary::getOwnPropertyNames(Vector<String>& names) const v8::Local<v8::String> key = properties->Get(i)->ToString(); if (!options->Has(key)) continue; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringKey, key, false); + TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); names.append(stringKey); } @@ -758,12 +738,7 @@ Dictionary::ConversionContext& Dictionary::ConversionContext::setConversionType( void Dictionary::ConversionContext::throwTypeError(const String& detail) { - if (forConstructor()) { - exceptionState().throwTypeError(detail); - } else { - ASSERT(!methodName().isEmpty()); - exceptionState().throwTypeError(ExceptionMessages::failedToExecute(interfaceName(), methodName(), detail)); - } + exceptionState().throwTypeError(detail); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.h b/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.h index 3f29651e876..2268c63bd2f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.h @@ -28,6 +28,7 @@ #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" +#include "bindings/v8/Nullable.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8BindingMacros.h" @@ -44,12 +45,14 @@ namespace WebCore { class ArrayValue; class DOMError; -class DOMWindow; +class LocalDOMWindow; +class Gamepad; +class MediaStream; +class HeaderMap; class IDBKeyRange; class MIDIPort; class MediaKeyError; class Notification; -class SpeechRecognitionError; class SpeechRecognitionResult; class SpeechRecognitionResultList; class Storage; @@ -57,6 +60,7 @@ class TrackBase; class VoidCallback; class Dictionary { + ALLOW_ONLY_INLINE_ALLOCATION(); public: Dictionary(); Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate*); @@ -72,32 +76,33 @@ public: bool get(const String&, double&, bool& hasValue) const; bool get(const String&, double&) const; bool get(const String&, String&) const; + bool get(const String&, AtomicString&) const; bool get(const String&, ScriptValue&) const; bool get(const String&, short&) const; bool get(const String&, unsigned short&) const; bool get(const String&, unsigned&) const; bool get(const String&, unsigned long&) const; bool get(const String&, unsigned long long&) const; - bool get(const String&, RefPtr<DOMWindow>&) const; - bool get(const String&, RefPtr<Storage>&) const; + bool get(const String&, RefPtrWillBeMember<LocalDOMWindow>&) const; + bool get(const String&, RefPtrWillBeMember<Storage>&) const; bool get(const String&, MessagePortArray&) const; bool get(const String&, RefPtr<Uint8Array>&) const; bool get(const String&, RefPtr<ArrayBufferView>&) const; - bool get(const String&, RefPtr<MIDIPort>&) const; + bool get(const String&, RefPtrWillBeMember<MIDIPort>&) const; bool get(const String&, RefPtr<MediaKeyError>&) const; - bool get(const String&, RefPtr<TrackBase>&) const; - bool get(const String&, RefPtr<SpeechRecognitionError>&) const; - bool get(const String&, RefPtr<SpeechRecognitionResult>&) const; - bool get(const String&, RefPtr<SpeechRecognitionResultList>&) const; + bool get(const String&, RefPtrWillBeMember<TrackBase>&) const; + bool get(const String&, Member<SpeechRecognitionResult>&) const; + bool get(const String&, Member<SpeechRecognitionResultList>&) const; + bool get(const String&, Member<Gamepad>&) const; bool get(const String&, RefPtr<MediaStream>&) const; - bool get(const String&, RefPtr<EventTarget>&) const; + bool get(const String&, RefPtrWillBeMember<EventTarget>&) const; bool get(const String&, HashSet<AtomicString>&) const; bool get(const String&, Dictionary&) const; bool get(const String&, Vector<String>&) const; bool get(const String&, ArrayValue&) const; - bool get(const String&, RefPtr<DOMError>&) const; - bool get(const String&, OwnPtr<VoidCallback>&) const; + bool get(const String&, RefPtrWillBeMember<DOMError>&) const; bool get(const String&, v8::Local<v8::Value>&) const; + bool get(const String&, RefPtr<HeaderMap>&) const; class ConversionContext { public: @@ -152,14 +157,20 @@ public: bool convert(ConversionContext&, const String&, ScriptValue&) const; template<typename IntegralType> - bool convert(ConversionContext &, const String&, IntegralType&) const; - bool convert(ConversionContext &, const String&, MessagePortArray&) const; - bool convert(ConversionContext &, const String&, HashSet<AtomicString>&) const; - bool convert(ConversionContext &, const String&, Dictionary&) const; - bool convert(ConversionContext &, const String&, Vector<String>&) const; - bool convert(ConversionContext &, const String&, ArrayValue&) const; - template<typename T> - bool convert(ConversionContext &, const String&, RefPtr<T>&) const; + bool convert(ConversionContext&, const String&, IntegralType&) const; + template<typename IntegralType> + bool convert(ConversionContext&, const String&, Nullable<IntegralType>&) const; + + bool convert(ConversionContext&, const String&, MessagePortArray&) const; + bool convert(ConversionContext&, const String&, HashSet<AtomicString>&) const; + bool convert(ConversionContext&, const String&, Dictionary&) const; + bool convert(ConversionContext&, const String&, Vector<String>&) const; + bool convert(ConversionContext&, const String&, ArrayValue&) const; + template<template <typename> class PointerType, typename T> + bool convert(ConversionContext&, const String&, PointerType<T>&) const; + + template<typename StringType> + bool getStringType(const String&, StringType&) const; bool getOwnPropertiesAsStringHashMap(HashMap<String, String>&) const; bool getOwnPropertyNames(Vector<String>&) const; @@ -168,13 +179,7 @@ public: bool hasProperty(const String&) const; - // Only allow inline allocation. - void* operator new(size_t, NotNullTag, void* location) { return location; } - private: - // Disallow new allocation. - void* operator new(size_t); - bool getKey(const String& key, v8::Local<v8::Value>&) const; v8::Handle<v8::Value> m_options; @@ -195,90 +200,90 @@ struct IntegralTypeTraits { template <> struct IntegralTypeTraits<uint8_t> { - static inline uint8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline uint8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toUInt8(value, configuration, ok); + return toUInt8(value, configuration, exceptionState); } static const String typeName() { return "UInt8"; } }; template <> struct IntegralTypeTraits<int8_t> { - static inline int8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline int8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toInt8(value, configuration, ok); + return toInt8(value, configuration, exceptionState); } static const String typeName() { return "Int8"; } }; template <> struct IntegralTypeTraits<unsigned short> { - static inline uint16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline uint16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toUInt16(value, configuration, ok); + return toUInt16(value, configuration, exceptionState); } static const String typeName() { return "UInt16"; } }; template <> struct IntegralTypeTraits<short> { - static inline int16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline int16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toInt16(value, configuration, ok); + return toInt16(value, configuration, exceptionState); } static const String typeName() { return "Int16"; } }; template <> struct IntegralTypeTraits<unsigned> { - static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toUInt32(value, configuration, ok); + return toUInt32(value, configuration, exceptionState); } static const String typeName() { return "UInt32"; } }; template <> struct IntegralTypeTraits<unsigned long> { - static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toUInt32(value, configuration, ok); + return toUInt32(value, configuration, exceptionState); } static const String typeName() { return "UInt32"; } }; template <> struct IntegralTypeTraits<int> { - static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toInt32(value, configuration, ok); + return toInt32(value, configuration, exceptionState); } static const String typeName() { return "Int32"; } }; template <> struct IntegralTypeTraits<long> { - static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toInt32(value, configuration, ok); + return toInt32(value, configuration, exceptionState); } static const String typeName() { return "Int32"; } }; template <> struct IntegralTypeTraits<unsigned long long> { - static inline unsigned long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline unsigned long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toUInt64(value, configuration, ok); + return toUInt64(value, configuration, exceptionState); } static const String typeName() { return "UInt64"; } }; template <> struct IntegralTypeTraits<long long> { - static inline long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toInt64(value, configuration, ok); + return toInt64(value, configuration, exceptionState); } static const String typeName() { return "Int64"; } }; @@ -291,18 +296,36 @@ template<typename T> bool Dictionary::convert(ConversionContext& context, const if (!getKey(key, v8Value)) return true; - bool ok = false; - value = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, ok); - if (ok) + value = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, context.exceptionState()); + if (context.exceptionState().throwIfNeeded()) + return false; + + return true; +} + +template<typename T> bool Dictionary::convert(ConversionContext& context, const String& key, Nullable<T>& value) const +{ + ConversionContextScope scope(context); + + v8::Local<v8::Value> v8Value; + if (!getKey(key, v8Value)) return true; - V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); - ASSERT(v8Number.IsEmpty()); - context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have type " + IntegralTypeTraits<T>::typeName() + ".")); - return false; + if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value)) { + value = Nullable<T>(); + return true; + } + + T converted = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, context.exceptionState()); + + if (context.exceptionState().throwIfNeeded()) + return false; + + value = Nullable<T>(converted); + return true; } -template<typename T> bool Dictionary::convert(ConversionContext& context, const String& key, RefPtr<T>& value) const +template<template <typename> class PointerType, typename T> bool Dictionary::convert(ConversionContext& context, const String& key, PointerType<T>& value) const { ConversionContextScope scope(context); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.cpp index beea8bef6d3..c65e04703d4 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.cpp @@ -31,33 +31,59 @@ #include "config.h" #include "bindings/v8/ExceptionMessages.h" +#include "platform/Decimal.h" #include "wtf/MathExtras.h" namespace WebCore { -String ExceptionMessages::failedToConstruct(const String& type, const String& detail) +String ExceptionMessages::failedToConstruct(const char* type, const String& detail) { - return "Failed to construct '" + type + (!detail.isEmpty() ? String("': " + detail) : String("'")); + return "Failed to construct '" + String(type) + (!detail.isEmpty() ? String("': " + detail) : String("'")); } -String ExceptionMessages::failedToExecute(const String& method, const String& type, const String& detail) +String ExceptionMessages::failedToEnumerate(const char* type, const String& detail) { - return "Failed to execute '" + method + "' on '" + type + (!detail.isEmpty() ? String("': " + detail) : String("'")); + return "Failed to enumerate the properties of '" + String(type) + (!detail.isEmpty() ? String("': " + detail) : String("'")); } -String ExceptionMessages::failedToGet(const String& property, const String& type, const String& detail) +String ExceptionMessages::failedToExecute(const char* method, const char* type, const String& detail) { - return "Failed to read the '" + property + "' property from '" + type + "': " + detail; + return "Failed to execute '" + String(method) + "' on '" + String(type) + (!detail.isEmpty() ? String("': " + detail) : String("'")); } -String ExceptionMessages::failedToSet(const String& property, const String& type, const String& detail) +String ExceptionMessages::failedToGet(const char* property, const char* type, const String& detail) { - return "Failed to set the '" + property + "' property on '" + type + "': " + detail; + return "Failed to read the '" + String(property) + "' property from '" + String(type) + "': " + detail; } -String ExceptionMessages::failedToDelete(const String& property, const String& type, const String& detail) +String ExceptionMessages::failedToSet(const char* property, const char* type, const String& detail) { - return "Failed to delete the '" + property + "' property from '" + type + "': " + detail; + return "Failed to set the '" + String(property) + "' property on '" + String(type) + "': " + detail; +} + +String ExceptionMessages::failedToDelete(const char* property, const char* type, const String& detail) +{ + return "Failed to delete the '" + String(property) + "' property from '" + String(type) + "': " + detail; +} + +String ExceptionMessages::failedToGetIndexed(const char* type, const String& detail) +{ + return "Failed to read an indexed property from '" + String(type) + "': " + detail; +} + +String ExceptionMessages::failedToSetIndexed(const char* type, const String& detail) +{ + return "Failed to set an indexed property on '" + String(type) + "': " + detail; +} + +String ExceptionMessages::failedToDeleteIndexed(const char* type, const String& detail) +{ + return "Failed to delete an indexed property from '" + String(type) + "': " + detail; +} + +String ExceptionMessages::constructorNotCallableAsFunction(const char* type) +{ + return failedToConstruct(type, "Please use the 'new' operator, this DOM object constructor cannot be called as a function."); } String ExceptionMessages::incorrectPropertyType(const String& property, const String& detail) @@ -65,9 +91,14 @@ String ExceptionMessages::incorrectPropertyType(const String& property, const St return "The '" + property + "' property " + detail; } -String ExceptionMessages::incorrectArgumentType(int argumentIndex, const String& detail) +String ExceptionMessages::invalidArity(const char* expected, unsigned provided) { - return "The " + ordinalNumber(argumentIndex) + " argument " + detail; + return "Valid arities are: " + String(expected) + ", but " + String::number(provided) + " arguments provided."; +} + +String ExceptionMessages::argumentNullOrIncorrectType(int argumentIndex, const String& expectedType) +{ + return "The " + ordinalNumber(argumentIndex) + " argument provided is either null, or an invalid " + expectedType + " object."; } String ExceptionMessages::notAnArrayTypeArgumentOrValue(int argumentIndex) @@ -90,10 +121,16 @@ String ExceptionMessages::notEnoughArguments(unsigned expected, unsigned provide return String::number(expected) + " argument" + (expected > 1 ? "s" : "") + " required, but only " + String::number(provided) + " present."; } -String ExceptionMessages::notAFiniteNumber(double value) +String ExceptionMessages::notAFiniteNumber(double value, const char* name) { ASSERT(!std::isfinite(value)); - return std::isinf(value) ? "The value provided is infinite." : "The value provided is not a number."; + return String::format("The %s is %s.", name, std::isinf(value) ? "infinite" : "not a number"); +} + +String ExceptionMessages::notAFiniteNumber(const Decimal& value, const char* name) +{ + ASSERT(!value.isFinite()); + return String::format("The %s is %s.", name, value.isInfinity() ? "infinite" : "not a number"); } String ExceptionMessages::ordinalNumber(int number) @@ -116,4 +153,22 @@ String ExceptionMessages::ordinalNumber(int number) return String::number(number) + suffix; } +String ExceptionMessages::readOnly(const char* detail) +{ + DEFINE_STATIC_LOCAL(String, readOnly, ("This object is read-only.")); + return detail ? String::format("This object is read-only, because %s.", detail) : readOnly; +} + +template <> +String ExceptionMessages::formatNumber<float>(float number) +{ + return formatPotentiallyNonFiniteNumber(number); +} + +template <> +String ExceptionMessages::formatNumber<double>(double number) +{ + return formatPotentiallyNonFiniteNumber(number); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.h b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.h index 92f8a9f5879..a74819b3970 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.h @@ -31,33 +31,134 @@ #ifndef ExceptionMessages_h #define ExceptionMessages_h +#include "wtf/MathExtras.h" +#include "wtf/text/StringBuilder.h" #include "wtf/text/WTFString.h" namespace WebCore { +class Decimal; + class ExceptionMessages { public: - static String failedToConstruct(const String& type, const String& detail = String()); - static String failedToExecute(const String& method, const String& type, const String& detail = String()); - static String failedToGet(const String& property, const String& type, const String& detail); - static String failedToSet(const String& property, const String& type, const String& detail); - static String failedToDelete(const String& property, const String& type, const String& detail); + enum BoundType { + InclusiveBound, + ExclusiveBound, + }; + + static String argumentNullOrIncorrectType(int argumentIndex, const String& expectedType); + static String constructorNotCallableAsFunction(const char* type); + + static String failedToConstruct(const char* type, const String& detail); + static String failedToEnumerate(const char* type, const String& detail); + static String failedToExecute(const char* method, const char* type, const String& detail); + static String failedToGet(const char* property, const char* type, const String& detail); + static String failedToSet(const char* property, const char* type, const String& detail); + static String failedToDelete(const char* property, const char* type, const String& detail); + static String failedToGetIndexed(const char* type, const String& detail); + static String failedToSetIndexed(const char* type, const String& detail); + static String failedToDeleteIndexed(const char* type, const String& detail); + + template <typename NumType> + static String formatNumber(NumType number) + { + return formatFiniteNumber(number); + } - static String incorrectArgumentType(int argumentIndex, const String& detail); static String incorrectPropertyType(const String& property, const String& detail); + template <typename NumberType> + static String indexExceedsMaximumBound(const char* name, NumberType given, NumberType bound) + { + bool eq = given == bound; + StringBuilder result; + result.append("The "); + result.append(name); + result.append(" provided ("); + result.append(formatNumber(given)); + result.append(") is greater than "); + result.append(eq ? "or equal to " : ""); + result.append("the maximum bound ("); + result.append(formatNumber(bound)); + result.append(")."); + return result.toString(); + } + + template <typename NumberType> + static String indexExceedsMinimumBound(const char* name, NumberType given, NumberType bound) + { + bool eq = given == bound; + StringBuilder result; + result.append("The "); + result.append(name); + result.append(" provided ("); + result.append(formatNumber(given)); + result.append(") is less than "); + result.append(eq ? "or equal to " : ""); + result.append("the minimum bound ("); + result.append(formatNumber(bound)); + result.append(")."); + return result.toString(); + } + + template <typename NumberType> + static String indexOutsideRange(const char* name, NumberType given, NumberType lowerBound, BoundType lowerType, NumberType upperBound, BoundType upperType) + { + StringBuilder result; + result.append("The "); + result.append(name); + result.append(" provided ("); + result.append(formatNumber(given)); + result.append(") is outside the range "); + result.append(lowerType == ExclusiveBound ? '(' : '['); + result.append(formatNumber(lowerBound)); + result.append(", "); + result.append(formatNumber(upperBound)); + result.append(upperType == ExclusiveBound ? ')' : ']'); + result.append('.'); + return result.toString(); + } + + static String invalidArity(const char* expected, unsigned provided); + // If > 0, the argument index that failed type check (1-indexed.) // If == 0, a (non-argument) value (e.g., a setter) failed the same check. static String notAnArrayTypeArgumentOrValue(int argumentIndex); static String notASequenceTypeProperty(const String& propertyName); - static String notAFiniteNumber(double value); + static String notAFiniteNumber(double value, const char* name = "value provided"); + static String notAFiniteNumber(const Decimal& value, const char* name = "value provided"); static String notEnoughArguments(unsigned expected, unsigned providedleastNumMandatoryParams); + static String readOnly(const char* detail = 0); + private: + template <typename NumType> + static String formatFiniteNumber(NumType number) + { + if (number > 1e20 || number < -1e20) + return String::format("%e", 1.0*number); + return String::number(number); + } + + template <typename NumType> + static String formatPotentiallyNonFiniteNumber(NumType number) + { + if (std::isnan(number)) + return "NaN"; + if (std::isinf(number)) + return number > 0 ? "Infinity" : "-Infinity"; + if (number > 1e20 || number < -1e20) + return String::format("%e", number); + return String::number(number); + } + static String ordinalNumber(int number); }; +template <> String ExceptionMessages::formatNumber<float>(float number); +template <> String ExceptionMessages::formatNumber<double>(double number); + } // namespace WebCore #endif // ExceptionMessages_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.cpp index 77c9103d7be..d51325cc41d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.cpp @@ -47,21 +47,26 @@ void ExceptionState::throwDOMException(const ExceptionCode& ec, const String& me { ASSERT(ec); ASSERT(m_isolate); + ASSERT(!m_creationContext.IsEmpty()); // SecurityError is thrown via ::throwSecurityError, and _careful_ consideration must be given to the data exposed to JavaScript via the 'sanitizedMessage'. ASSERT(ec != SecurityError); m_code = ec; String processedMessage = addExceptionContext(message); + m_message = processedMessage; setException(V8ThrowException::createDOMException(ec, processedMessage, m_creationContext, m_isolate)); } void ExceptionState::throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage) { ASSERT(m_isolate); + ASSERT(!m_creationContext.IsEmpty()); m_code = SecurityError; String finalSanitized = addExceptionContext(sanitizedMessage); + m_message = finalSanitized; String finalUnsanitized = addExceptionContext(unsanitizedMessage); + setException(V8ThrowException::createDOMException(SecurityError, finalSanitized, finalUnsanitized, m_creationContext, m_isolate)); } @@ -76,26 +81,57 @@ void ExceptionState::setException(v8::Handle<v8::Value> exception) m_exception.set(m_isolate, exception); } +void ExceptionState::throwException() +{ + ASSERT(!m_exception.isEmpty()); + V8ThrowException::throwError(m_exception.newLocal(m_isolate), m_isolate); +} + void ExceptionState::throwTypeError(const String& message) { ASSERT(m_isolate); m_code = TypeError; + m_message = message; setException(V8ThrowException::createTypeError(addExceptionContext(message), m_isolate)); } +void NonThrowableExceptionState::throwDOMException(const ExceptionCode& ec, const String& message) +{ + ASSERT_NOT_REACHED(); + m_code = ec; + m_message = message; +} + +void NonThrowableExceptionState::throwTypeError(const String& message) +{ + ASSERT_NOT_REACHED(); + m_code = TypeError; + m_message = message; +} + +void NonThrowableExceptionState::throwSecurityError(const String& sanitizedMessage, const String&) +{ + ASSERT_NOT_REACHED(); + m_code = SecurityError; + m_message = sanitizedMessage; +} + void TrackExceptionState::throwDOMException(const ExceptionCode& ec, const String& message) { m_code = ec; + m_message = message; } -void TrackExceptionState::throwTypeError(const String&) +void TrackExceptionState::throwTypeError(const String& message) { m_code = TypeError; + m_message = message; } -void TrackExceptionState::throwSecurityError(const String&, const String&) +void TrackExceptionState::throwSecurityError(const String& sanitizedMessage, const String&) { m_code = SecurityError; + m_message = sanitizedMessage; } String ExceptionState::addExceptionContext(const String& message) const @@ -113,8 +149,17 @@ String ExceptionState::addExceptionContext(const String& message) const processedMessage = ExceptionMessages::failedToGet(propertyName(), interfaceName(), message); else if (m_context == SetterContext) processedMessage = ExceptionMessages::failedToSet(propertyName(), interfaceName(), message); - } else if (!propertyName() && interfaceName() && m_context == ConstructionContext) { - processedMessage = ExceptionMessages::failedToConstruct(interfaceName(), message); + } else if (!propertyName() && interfaceName()) { + if (m_context == ConstructionContext) + processedMessage = ExceptionMessages::failedToConstruct(interfaceName(), message); + else if (m_context == EnumerationContext) + processedMessage = ExceptionMessages::failedToEnumerate(interfaceName(), message); + else if (m_context == IndexedDeletionContext) + processedMessage = ExceptionMessages::failedToDeleteIndexed(interfaceName(), message); + else if (m_context == IndexedGetterContext) + processedMessage = ExceptionMessages::failedToGetIndexed(interfaceName(), message); + else if (m_context == IndexedSetterContext) + processedMessage = ExceptionMessages::failedToSetIndexed(interfaceName(), message); } return processedMessage; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.h b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.h index bfe2790e16a..d9c2b05b8ef 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.h @@ -50,17 +50,14 @@ public: DeletionContext, GetterContext, SetterContext, + EnumerationContext, + QueryContext, + IndexedGetterContext, + IndexedSetterContext, + IndexedDeletionContext, UnknownContext, // FIXME: Remove this once we've flipped over to the new API. }; - explicit ExceptionState(const v8::Handle<v8::Object>& creationContext, v8::Isolate* isolate) - : m_code(0) - , m_context(UnknownContext) - , m_propertyName(0) - , m_interfaceName(0) - , m_creationContext(creationContext) - , m_isolate(isolate) { } - ExceptionState(Context context, const char* propertyName, const char* interfaceName, const v8::Handle<v8::Object>& creationContext, v8::Isolate* isolate) : m_code(0) , m_context(context) @@ -75,30 +72,23 @@ public: , m_propertyName(0) , m_interfaceName(interfaceName) , m_creationContext(creationContext) - , m_isolate(isolate) { ASSERT(m_context == ConstructionContext); } + , m_isolate(isolate) { ASSERT(m_context == ConstructionContext || m_context == EnumerationContext || m_context == IndexedSetterContext || m_context == IndexedGetterContext || m_context == IndexedDeletionContext); } virtual void throwDOMException(const ExceptionCode&, const String& message); virtual void throwTypeError(const String& message); virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()); - // Please don't use these methods. Use ::throwDOMException and ::throwTypeError, and pass in a useful exception message. - virtual void throwUninformativeAndGenericDOMException(const ExceptionCode& ec) { throwDOMException(ec, String()); } - virtual void throwUninformativeAndGenericTypeError() { throwTypeError(String()); } - bool hadException() const { return !m_exception.isEmpty() || m_code; } void clearException(); ExceptionCode code() const { return m_code; } + const String& message() const { return m_message; } bool throwIfNeeded() { - if (m_exception.isEmpty()) { - if (!m_code) - return false; - throwUninformativeAndGenericDOMException(m_code); - } - - V8ThrowException::throwError(m_exception.newLocal(m_isolate), m_isolate); + if (!hadException()) + return false; + throwException(); return true; } @@ -106,14 +96,21 @@ public: const char* propertyName() const { return m_propertyName; } const char* interfaceName() const { return m_interfaceName; } + void rethrowV8Exception(v8::Handle<v8::Value> value) + { + setException(value); + } + protected: ExceptionCode m_code; Context m_context; + String m_message; const char* m_propertyName; const char* m_interfaceName; private: void setException(v8::Handle<v8::Value>); + void throwException(); String addExceptionContext(const String&) const; @@ -122,12 +119,22 @@ private: v8::Isolate* m_isolate; }; -class TrackExceptionState : public ExceptionState { +// Used if exceptions can/should not be directly thrown. +class NonThrowableExceptionState FINAL : public ExceptionState { +public: + NonThrowableExceptionState(): ExceptionState(ExceptionState::UnknownContext, 0, 0, v8::Handle<v8::Object>(), v8::Isolate::GetCurrent()) { } + virtual void throwDOMException(const ExceptionCode&, const String& message) OVERRIDE; + virtual void throwTypeError(const String& message = String()) OVERRIDE; + virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE; +}; + +// Used if any exceptions thrown are ignorable. +class TrackExceptionState FINAL : public ExceptionState { public: - TrackExceptionState(): ExceptionState(v8::Handle<v8::Object>(), 0) { } - virtual void throwDOMException(const ExceptionCode&, const String& message) OVERRIDE FINAL; - virtual void throwTypeError(const String& message = String()) OVERRIDE FINAL; - virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE FINAL; + TrackExceptionState(): ExceptionState(ExceptionState::UnknownContext, 0, 0, v8::Handle<v8::Object>(), v8::Isolate::GetCurrent()) { } + virtual void throwDOMException(const ExceptionCode&, const String& message) OVERRIDE; + virtual void throwTypeError(const String& message = String()) OVERRIDE; + virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.cpp index 9d33119c814..6cfb6b2452e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.cpp @@ -33,10 +33,10 @@ namespace WebCore { -#if !ASSERT_DISABLED +#if ASSERT_ENABLED NoExceptionStateAssertionChecker::NoExceptionStateAssertionChecker(const char* file, int line) - : ExceptionState(v8::Handle<v8::Object>(), 0) + : ExceptionState(ExceptionState::UnknownContext, 0, 0, v8::Handle<v8::Object>(), 0) , m_file(file) , m_line(line) { } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.h b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.h index 84f6eb0b0f6..6df5b1ab9bb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.h @@ -34,6 +34,7 @@ #include "bindings/v8/ExceptionState.h" #include "wtf/Assertions.h" #include "wtf/text/WTFString.h" +#include <v8.h> namespace WebCore { @@ -41,30 +42,26 @@ class ExceptionState; typedef int ExceptionCode; -class IgnorableExceptionState : public ExceptionState { +class IgnorableExceptionState FINAL : public ExceptionState { public: - IgnorableExceptionState(): ExceptionState(v8::Handle<v8::Object>(), 0) { } + IgnorableExceptionState(): ExceptionState(ExceptionState::UnknownContext, 0, 0, v8::Handle<v8::Object>(), 0) { } ExceptionState& returnThis() { return *this; } - virtual void throwDOMException(const ExceptionCode&, const String& message = String()) OVERRIDE FINAL { }; - virtual void throwTypeError(const String& message = String()) OVERRIDE FINAL { } - virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE FINAL { } + virtual void throwDOMException(const ExceptionCode&, const String& message = String()) OVERRIDE { } + virtual void throwTypeError(const String& message = String()) OVERRIDE { } + virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE { } }; #define IGNORE_EXCEPTION (::WebCore::IgnorableExceptionState().returnThis()) -#if ASSERT_DISABLED +#if ASSERT_ENABLED -#define ASSERT_NO_EXCEPTION (::WebCore::IgnorableExceptionState().returnThis()) - -#else - -class NoExceptionStateAssertionChecker : public ExceptionState { +class NoExceptionStateAssertionChecker FINAL : public ExceptionState { public: NoExceptionStateAssertionChecker(const char* file, int line); ExceptionState& returnThis() { return *this; } - virtual void throwDOMException(const ExceptionCode&, const String& message = String()) OVERRIDE FINAL; - virtual void throwTypeError(const String& message = String()) OVERRIDE FINAL; - virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE FINAL; + virtual void throwDOMException(const ExceptionCode&, const String& message = String()) OVERRIDE; + virtual void throwTypeError(const String& message = String()) OVERRIDE; + virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE; private: const char* m_file; @@ -73,6 +70,10 @@ private: #define ASSERT_NO_EXCEPTION (::WebCore::NoExceptionStateAssertionChecker(__FILE__, __LINE__).returnThis()) +#else + +#define ASSERT_NO_EXCEPTION (::WebCore::IgnorableExceptionState().returnThis()) + #endif } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.cpp b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.cpp index 1676649e556..bc50f3c7a8a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.cpp @@ -26,23 +26,25 @@ #include "config.h" #include "bindings/v8/IDBBindingUtilities.h" -#include "V8DOMStringList.h" -#include "V8IDBCursor.h" -#include "V8IDBCursorWithValue.h" -#include "V8IDBDatabase.h" -#include "V8IDBIndex.h" -#include "V8IDBKeyRange.h" -#include "V8IDBObjectStore.h" -#include "V8IDBTransaction.h" -#include "bindings/v8/DOMRequestState.h" +#include "bindings/core/v8/V8DOMStringList.h" +#include "bindings/modules/v8/V8IDBCursor.h" +#include "bindings/modules/v8/V8IDBCursorWithValue.h" +#include "bindings/modules/v8/V8IDBDatabase.h" +#include "bindings/modules/v8/V8IDBIndex.h" +#include "bindings/modules/v8/V8IDBKeyRange.h" +#include "bindings/modules/v8/V8IDBObjectStore.h" +#include "bindings/modules/v8/V8IDBRequest.h" +#include "bindings/modules/v8/V8IDBTransaction.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "bindings/v8/custom/V8Uint8ArrayCustom.h" #include "modules/indexeddb/IDBKey.h" #include "modules/indexeddb/IDBKeyPath.h" #include "modules/indexeddb/IDBKeyRange.h" #include "modules/indexeddb/IDBTracing.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/SharedBuffer.h" #include "wtf/ArrayBufferView.h" #include "wtf/MathExtras.h" @@ -51,7 +53,7 @@ namespace WebCore { -v8::Handle<v8::Value> deserializeIDBValueBuffer(SharedBuffer*, v8::Isolate*); +static v8::Handle<v8::Value> deserializeIDBValueBuffer(v8::Isolate*, SharedBuffer*, const Vector<blink::WebBlobInfo>*); static v8::Handle<v8::Value> toV8(const IDBKeyPath& value, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { @@ -61,7 +63,7 @@ static v8::Handle<v8::Value> toV8(const IDBKeyPath& value, v8::Handle<v8::Object case IDBKeyPath::StringType: return v8String(isolate, value.string()); case IDBKeyPath::ArrayType: - RefPtr<DOMStringList> keyPaths = DOMStringList::create(); + RefPtrWillBeRawPtr<DOMStringList> keyPaths = DOMStringList::create(); for (Vector<String>::const_iterator it = value.array().begin(); it != value.array().end(); ++it) keyPaths->append(*it); return toV8(keyPaths.release(), creationContext, isolate); @@ -70,7 +72,7 @@ static v8::Handle<v8::Value> toV8(const IDBKeyPath& value, v8::Handle<v8::Object return v8::Undefined(isolate); } -v8::Handle<v8::Value> toV8(const IDBKey* key, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +static v8::Handle<v8::Value> toV8(const IDBKey* key, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { if (!key) { // This should be undefined, not null. @@ -104,7 +106,7 @@ v8::Handle<v8::Value> toV8(const IDBKey* key, v8::Handle<v8::Object> creationCon return v8Undefined(); } -v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +static v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { if (!impl) return v8::Null(isolate); @@ -116,10 +118,22 @@ v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationCo return v8::Null(isolate); case IDBAny::DOMStringListType: return toV8(impl->domStringList(), creationContext, isolate); - case IDBAny::IDBCursorType: - return toV8(impl->idbCursor(), creationContext, isolate); - case IDBAny::IDBCursorWithValueType: - return toV8(impl->idbCursorWithValue(), creationContext, isolate); + case IDBAny::IDBCursorType: { + // Ensure request wrapper is kept alive at least as long as the cursor wrapper, + // so that event listeners are retained. + v8::Handle<v8::Value> cursor = toV8(impl->idbCursor(), creationContext, isolate); + v8::Handle<v8::Value> request = toV8(impl->idbCursor()->request(), creationContext, isolate); + V8HiddenValue::setHiddenValue(isolate, cursor->ToObject(), V8HiddenValue::idbCursorRequest(isolate), request); + return cursor; + } + case IDBAny::IDBCursorWithValueType: { + // Ensure request wrapper is kept alive at least as long as the cursor wrapper, + // so that event listeners are retained. + v8::Handle<v8::Value> cursor = toV8(impl->idbCursorWithValue(), creationContext, isolate); + v8::Handle<v8::Value> request = toV8(impl->idbCursorWithValue()->request(), creationContext, isolate); + V8HiddenValue::setHiddenValue(isolate, cursor->ToObject(), V8HiddenValue::idbCursorRequest(isolate), request); + return cursor; + } case IDBAny::IDBDatabaseType: return toV8(impl->idbDatabase(), creationContext, isolate); case IDBAny::IDBIndexType: @@ -129,7 +143,7 @@ v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationCo case IDBAny::IDBTransactionType: return toV8(impl->idbTransaction(), creationContext, isolate); case IDBAny::BufferType: - return deserializeIDBValueBuffer(impl->buffer(), isolate); + return deserializeIDBValueBuffer(isolate, impl->buffer(), impl->blobInfo()); case IDBAny::StringType: return v8String(isolate, impl->string()); case IDBAny::IntegerType: @@ -139,9 +153,9 @@ v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationCo case IDBAny::KeyPathType: return toV8(impl->keyPath(), creationContext, isolate); case IDBAny::BufferKeyAndKeyPathType: { - v8::Handle<v8::Value> value = deserializeIDBValueBuffer(impl->buffer(), isolate); + v8::Handle<v8::Value> value = deserializeIDBValueBuffer(isolate, impl->buffer(), impl->blobInfo()); v8::Handle<v8::Value> key = toV8(impl->key(), creationContext, isolate); - bool injected = injectV8KeyIntoV8Value(key, value, impl->keyPath(), isolate); + bool injected = injectV8KeyIntoV8Value(isolate, key, value, impl->keyPath()); ASSERT_UNUSED(injected, injected); return value; } @@ -153,7 +167,7 @@ v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationCo static const size_t maximumDepth = 2000; -static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, Vector<v8::Handle<v8::Array> >& stack, v8::Isolate* isolate) +static IDBKey* createIDBKeyFromValue(v8::Isolate* isolate, v8::Handle<v8::Value> value, Vector<v8::Handle<v8::Array> >& stack, bool allowExperimentalTypes = false) { if (value->IsNumber() && !std::isnan(value->NumberValue())) return IDBKey::createNumber(value->NumberValue()); @@ -161,6 +175,14 @@ static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, Vec return IDBKey::createString(toCoreString(value.As<v8::String>())); if (value->IsDate() && !std::isnan(value->NumberValue())) return IDBKey::createDate(value->NumberValue()); + if (value->IsUint8Array() && (allowExperimentalTypes || RuntimeEnabledFeatures::indexedDBExperimentalEnabled())) { + // Per discussion in https://www.w3.org/Bugs/Public/show_bug.cgi?id=23332 the + // input type is constrained to Uint8Array to match the output type. + ArrayBufferView* view = WebCore::V8ArrayBufferView::toNative(value->ToObject()); + const char* start = static_cast<const char*>(view->baseAddress()); + size_t length = view->byteLength(); + return IDBKey::createBinary(SharedBuffer::create(start, length)); + } if (value->IsArray()) { v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); @@ -173,8 +195,8 @@ static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, Vec IDBKey::KeyArray subkeys; uint32_t length = array->Length(); for (uint32_t i = 0; i < length; ++i) { - v8::Local<v8::Value> item = array->Get(v8::Int32::New(i, isolate)); - RefPtr<IDBKey> subkey = createIDBKeyFromValue(item, stack, isolate); + v8::Local<v8::Value> item = array->Get(v8::Int32::New(isolate, i)); + IDBKey* subkey = createIDBKeyFromValue(isolate, item, stack, allowExperimentalTypes); if (!subkey) subkeys.append(IDBKey::createInvalid()); else @@ -187,11 +209,10 @@ static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, Vec return 0; } -static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, v8::Isolate* isolate) +static IDBKey* createIDBKeyFromValue(v8::Isolate* isolate, v8::Handle<v8::Value> value, bool allowExperimentalTypes = false) { Vector<v8::Handle<v8::Array> > stack; - RefPtr<IDBKey> key = createIDBKeyFromValue(value, stack, isolate); - if (key) + if (IDBKey* key = createIDBKeyFromValue(isolate, value, stack, allowExperimentalTypes)) return key; return IDBKey::createInvalid(); } @@ -213,7 +234,7 @@ static bool setValue(v8::Handle<v8::Value>& v8Object, T indexOrName, const v8::H return object->Set(indexOrName, v8Value); } -static bool get(v8::Handle<v8::Value>& object, const String& keyPathElement, v8::Handle<v8::Value>& result, v8::Isolate* isolate) +static bool get(v8::Isolate* isolate, v8::Handle<v8::Value>& object, const String& keyPathElement, v8::Handle<v8::Value>& result) { if (object->IsString() && keyPathElement == "length") { int32_t length = v8::Handle<v8::String>::Cast(object)->Length(); @@ -228,25 +249,25 @@ static bool canSet(v8::Handle<v8::Value>& object, const String& keyPathElement) return object->IsObject(); } -static bool set(v8::Handle<v8::Value>& object, const String& keyPathElement, const v8::Handle<v8::Value>& v8Value, v8::Isolate* isolate) +static bool set(v8::Isolate* isolate, v8::Handle<v8::Value>& object, const String& keyPathElement, const v8::Handle<v8::Value>& v8Value) { return canSet(object, keyPathElement) && setValue(object, v8String(isolate, keyPathElement), v8Value); } -static v8::Handle<v8::Value> getNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index, v8::Isolate* isolate) +static v8::Handle<v8::Value> getNthValueOnKeyPath(v8::Isolate* isolate, v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index) { v8::Handle<v8::Value> currentValue(rootValue); ASSERT(index <= keyPathElements.size()); for (size_t i = 0; i < index; ++i) { v8::Handle<v8::Value> parentValue(currentValue); - if (!get(parentValue, keyPathElements[i], currentValue, isolate)) + if (!get(isolate, parentValue, keyPathElements[i], currentValue)) return v8Undefined(); } return currentValue; } -static bool canInjectNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index, v8::Isolate* isolate) +static bool canInjectNthValueOnKeyPath(v8::Isolate* isolate, v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index) { if (!rootValue->IsObject()) return false; @@ -257,14 +278,14 @@ static bool canInjectNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const V for (size_t i = 0; i < index; ++i) { v8::Handle<v8::Value> parentValue(currentValue); const String& keyPathElement = keyPathElements[i]; - if (!get(parentValue, keyPathElement, currentValue, isolate)) + if (!get(isolate, parentValue, keyPathElement, currentValue)) return canSet(parentValue, keyPathElement); } return true; } -static v8::Handle<v8::Value> ensureNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index, v8::Isolate* isolate) +static v8::Handle<v8::Value> ensureNthValueOnKeyPath(v8::Isolate* isolate, v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index) { v8::Handle<v8::Value> currentValue(rootValue); @@ -272,9 +293,9 @@ static v8::Handle<v8::Value> ensureNthValueOnKeyPath(v8::Handle<v8::Value>& root for (size_t i = 0; i < index; ++i) { v8::Handle<v8::Value> parentValue(currentValue); const String& keyPathElement = keyPathElements[i]; - if (!get(parentValue, keyPathElement, currentValue, isolate)) { - v8::Handle<v8::Object> object = v8::Object::New(); - if (!set(parentValue, keyPathElement, object, isolate)) + if (!get(isolate, parentValue, keyPathElement, currentValue)) { + v8::Handle<v8::Object> object = v8::Object::New(isolate); + if (!set(isolate, parentValue, keyPathElement, object)) return v8Undefined(); currentValue = object; } @@ -283,7 +304,7 @@ static v8::Handle<v8::Value> ensureNthValueOnKeyPath(v8::Handle<v8::Value>& root return currentValue; } -static PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(const ScriptValue& value, const String& keyPath, v8::Isolate* isolate) +static IDBKey* createIDBKeyFromScriptValueAndKeyPathInternal(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath, bool allowExperimentalTypes) { Vector<String> keyPathElements; IDBKeyPathParseError error; @@ -293,24 +314,21 @@ static PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(const ScriptValu v8::HandleScope handleScope(isolate); v8::Handle<v8::Value> v8Value(value.v8Value()); - v8::Handle<v8::Value> v8Key(getNthValueOnKeyPath(v8Value, keyPathElements, keyPathElements.size(), isolate)); + v8::Handle<v8::Value> v8Key(getNthValueOnKeyPath(isolate, v8Value, keyPathElements, keyPathElements.size())); if (v8Key.IsEmpty()) return 0; - return createIDBKeyFromValue(v8Key, isolate); + return createIDBKeyFromValue(isolate, v8Key, allowExperimentalTypes); } -PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState* state, const ScriptValue& value, const IDBKeyPath& keyPath) +static IDBKey* createIDBKeyFromScriptValueAndKeyPathInternal(v8::Isolate* isolate, const ScriptValue& value, const IDBKeyPath& keyPath, bool allowExperimentalTypes = false) { - IDB_TRACE("createIDBKeyFromScriptValueAndKeyPath"); ASSERT(!keyPath.isNull()); - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); v8::HandleScope handleScope(isolate); if (keyPath.type() == IDBKeyPath::ArrayType) { IDBKey::KeyArray result; const Vector<String>& array = keyPath.array(); for (size_t i = 0; i < array.size(); ++i) { - RefPtr<IDBKey> key = createIDBKeyFromScriptValueAndKeyPath(value, array[i], isolate); + IDBKey* key = createIDBKeyFromScriptValueAndKeyPathInternal(isolate, value, array[i], allowExperimentalTypes); if (!key) return 0; result.append(key); @@ -319,10 +337,16 @@ PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState* state, } ASSERT(keyPath.type() == IDBKeyPath::StringType); - return createIDBKeyFromScriptValueAndKeyPath(value, keyPath.string(), isolate); + return createIDBKeyFromScriptValueAndKeyPathInternal(isolate, value, keyPath.string(), allowExperimentalTypes); +} + +IDBKey* createIDBKeyFromScriptValueAndKeyPath(v8::Isolate* isolate, const ScriptValue& value, const IDBKeyPath& keyPath) +{ + IDB_TRACE("createIDBKeyFromScriptValueAndKeyPath"); + return createIDBKeyFromScriptValueAndKeyPathInternal(isolate, value, keyPath); } -v8::Handle<v8::Value> deserializeIDBValueBuffer(SharedBuffer* buffer, v8::Isolate* isolate) +static v8::Handle<v8::Value> deserializeIDBValueBuffer(v8::Isolate* isolate, SharedBuffer* buffer, const Vector<blink::WebBlobInfo>* blobInfo) { ASSERT(isolate->InContext()); if (!buffer) @@ -332,10 +356,10 @@ v8::Handle<v8::Value> deserializeIDBValueBuffer(SharedBuffer* buffer, v8::Isolat Vector<uint8_t> value; value.append(buffer->data(), buffer->size()); RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::createFromWireBytes(value); - return serializedValue->deserialize(isolate); + return serializedValue->deserialize(isolate, 0, blobInfo); } -bool injectV8KeyIntoV8Value(v8::Handle<v8::Value> key, v8::Handle<v8::Value> value, const IDBKeyPath& keyPath, v8::Isolate* isolate) +bool injectV8KeyIntoV8Value(v8::Isolate* isolate, v8::Handle<v8::Value> key, v8::Handle<v8::Value> value, const IDBKeyPath& keyPath) { IDB_TRACE("injectIDBV8KeyIntoV8Value"); ASSERT(isolate->InContext()); @@ -350,17 +374,17 @@ bool injectV8KeyIntoV8Value(v8::Handle<v8::Value> key, v8::Handle<v8::Value> val return false; v8::HandleScope handleScope(isolate); - v8::Handle<v8::Value> parent(ensureNthValueOnKeyPath(value, keyPathElements, keyPathElements.size() - 1, isolate)); + v8::Handle<v8::Value> parent(ensureNthValueOnKeyPath(isolate, value, keyPathElements, keyPathElements.size() - 1)); if (parent.IsEmpty()) return false; - if (!set(parent, keyPathElements.last(), key, isolate)) + if (!set(isolate, parent, keyPathElements.last(), key)) return false; return true; } -bool canInjectIDBKeyIntoScriptValue(DOMRequestState* state, const ScriptValue& scriptValue, const IDBKeyPath& keyPath) +bool canInjectIDBKeyIntoScriptValue(v8::Isolate* isolate, const ScriptValue& scriptValue, const IDBKeyPath& keyPath) { IDB_TRACE("canInjectIDBKeyIntoScriptValue"); ASSERT(keyPath.type() == IDBKeyPath::StringType); @@ -373,63 +397,54 @@ bool canInjectIDBKeyIntoScriptValue(DOMRequestState* state, const ScriptValue& s return false; v8::Handle<v8::Value> v8Value(scriptValue.v8Value()); - return canInjectNthValueOnKeyPath(v8Value, keyPathElements, keyPathElements.size() - 1, state->context()->GetIsolate()); + return canInjectNthValueOnKeyPath(isolate, v8Value, keyPathElements, keyPathElements.size() - 1); } -ScriptValue idbAnyToScriptValue(DOMRequestState* state, PassRefPtr<IDBAny> any) +ScriptValue idbAnyToScriptValue(ScriptState* scriptState, IDBAny* any) { - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); - v8::Local<v8::Context> context = state ? state->context() : isolate->GetCurrentContext(); + v8::Isolate* isolate = scriptState->isolate(); v8::HandleScope handleScope(isolate); - v8::Handle<v8::Value> v8Value(toV8(any.get(), context->Global(), isolate)); - return ScriptValue(v8Value, isolate); + v8::Handle<v8::Value> v8Value(toV8(any, scriptState->context()->Global(), isolate)); + return ScriptValue(scriptState, v8Value); } -ScriptValue idbKeyToScriptValue(DOMRequestState* state, PassRefPtr<IDBKey> key) +ScriptValue idbKeyToScriptValue(ScriptState* scriptState, IDBKey* key) { - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); - v8::Local<v8::Context> context = state ? state->context() : isolate->GetCurrentContext(); + v8::Isolate* isolate = scriptState->isolate(); v8::HandleScope handleScope(isolate); - v8::Handle<v8::Value> v8Value(toV8(key.get(), context->Global(), isolate)); - return ScriptValue(v8Value, isolate); + v8::Handle<v8::Value> v8Value(toV8(key, scriptState->context()->Global(), isolate)); + return ScriptValue(scriptState, v8Value); } -PassRefPtr<IDBKey> scriptValueToIDBKey(DOMRequestState* state, const ScriptValue& scriptValue) +IDBKey* scriptValueToIDBKey(v8::Isolate* isolate, const ScriptValue& scriptValue) { - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); ASSERT(isolate->InContext()); v8::HandleScope handleScope(isolate); v8::Handle<v8::Value> v8Value(scriptValue.v8Value()); - return createIDBKeyFromValue(v8Value, isolate); + return createIDBKeyFromValue(isolate, v8Value); } -PassRefPtr<IDBKeyRange> scriptValueToIDBKeyRange(DOMRequestState* state, const ScriptValue& scriptValue) +IDBKeyRange* scriptValueToIDBKeyRange(v8::Isolate* isolate, const ScriptValue& scriptValue) { - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); v8::Handle<v8::Value> value(scriptValue.v8Value()); - if (V8IDBKeyRange::hasInstance(value, isolate, worldType(isolate))) - return V8IDBKeyRange::toNative(value.As<v8::Object>()); - return 0; + return V8IDBKeyRange::toNativeWithTypeCheck(isolate, value); } #ifndef NDEBUG -void assertPrimaryKeyValidOrInjectable(DOMRequestState* state, PassRefPtr<SharedBuffer> buffer, PassRefPtr<IDBKey> prpKey, const IDBKeyPath& keyPath) +void assertPrimaryKeyValidOrInjectable(ScriptState* scriptState, PassRefPtr<SharedBuffer> buffer, const Vector<blink::WebBlobInfo>* blobInfo, IDBKey* key, const IDBKeyPath& keyPath) { - RefPtr<IDBKey> key(prpKey); - - DOMRequestState::Scope scope(*state); - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); - - ScriptValue keyValue = idbKeyToScriptValue(state, key); - ScriptValue scriptValue(deserializeIDBValueBuffer(buffer.get(), isolate), isolate); + ScriptState::Scope scope(scriptState); + v8::Isolate* isolate = scriptState->isolate(); + ScriptValue keyValue = idbKeyToScriptValue(scriptState, key); + ScriptValue scriptValue(scriptState, deserializeIDBValueBuffer(isolate, buffer.get(), blobInfo)); - RefPtr<IDBKey> expectedKey = createIDBKeyFromScriptValueAndKeyPath(state, scriptValue, keyPath); - ASSERT(!expectedKey || expectedKey->isEqual(key.get())); + // This assertion is about already persisted data, so allow experimental types. + const bool allowExperimentalTypes = true; + IDBKey* expectedKey = createIDBKeyFromScriptValueAndKeyPathInternal(isolate, scriptValue, keyPath, allowExperimentalTypes); + ASSERT(!expectedKey || expectedKey->isEqual(key)); - bool injected = injectV8KeyIntoV8Value(keyValue.v8Value(), scriptValue.v8Value(), keyPath, isolate); + bool injected = injectV8KeyIntoV8Value(isolate, keyValue.v8Value(), scriptValue.v8Value(), keyPath); ASSERT_UNUSED(injected, injected); } #endif diff --git a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.h b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.h index b36c71cb03d..fba64423937 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.h @@ -26,13 +26,19 @@ #ifndef IDBBindingUtilities_h #define IDBBindingUtilities_h +#include "bindings/v8/ScriptState.h" #include "bindings/v8/ScriptValue.h" #include <v8.h> #include "wtf/Forward.h" +namespace blink { + +class WebBlobInfo; + +} + namespace WebCore { -class DOMRequestState; class IDBAny; class IDBKey; class IDBKeyPath; @@ -41,18 +47,18 @@ class SerializedScriptValue; class SharedBuffer; // Exposed for unit testing: -bool injectV8KeyIntoV8Value(v8::Handle<v8::Value> key, v8::Handle<v8::Value>, const IDBKeyPath&, v8::Isolate*); +bool injectV8KeyIntoV8Value(v8::Isolate*, v8::Handle<v8::Value> key, v8::Handle<v8::Value>, const IDBKeyPath&); // For use by Source/modules/indexeddb: -PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState*, const ScriptValue&, const IDBKeyPath&); -bool canInjectIDBKeyIntoScriptValue(DOMRequestState*, const ScriptValue&, const IDBKeyPath&); -ScriptValue idbAnyToScriptValue(DOMRequestState*, PassRefPtr<IDBAny>); -ScriptValue idbKeyToScriptValue(DOMRequestState*, PassRefPtr<IDBKey>); -PassRefPtr<IDBKey> scriptValueToIDBKey(DOMRequestState*, const ScriptValue&); -PassRefPtr<IDBKeyRange> scriptValueToIDBKeyRange(DOMRequestState*, const ScriptValue&); +IDBKey* createIDBKeyFromScriptValueAndKeyPath(v8::Isolate*, const ScriptValue&, const IDBKeyPath&); +bool canInjectIDBKeyIntoScriptValue(v8::Isolate*, const ScriptValue&, const IDBKeyPath&); +ScriptValue idbAnyToScriptValue(ScriptState*, IDBAny*); +ScriptValue idbKeyToScriptValue(ScriptState*, IDBKey*); +IDBKey* scriptValueToIDBKey(v8::Isolate*, const ScriptValue&); +IDBKeyRange* scriptValueToIDBKeyRange(v8::Isolate*, const ScriptValue&); #ifndef NDEBUG -void assertPrimaryKeyValidOrInjectable(DOMRequestState*, PassRefPtr<SharedBuffer>, PassRefPtr<IDBKey>, const IDBKeyPath&); +void assertPrimaryKeyValidOrInjectable(ScriptState*, PassRefPtr<SharedBuffer>, const Vector<blink::WebBlobInfo>*, IDBKey*, const IDBKeyPath&); #endif } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilitiesTest.cpp b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilitiesTest.cpp index 0f6ff63ee32..b984d04ceeb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilitiesTest.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilitiesTest.cpp @@ -28,64 +28,60 @@ #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8PerIsolateData.h" -#include "bindings/v8/V8Utilities.h" #include "modules/indexeddb/IDBKey.h" #include "modules/indexeddb/IDBKeyPath.h" - #include <gtest/gtest.h> using namespace WebCore; namespace { -PassRefPtr<IDBKey> checkKeyFromValueAndKeyPathInternal(const ScriptValue& value, const String& keyPath) +IDBKey* checkKeyFromValueAndKeyPathInternal(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath) { IDBKeyPath idbKeyPath(keyPath); EXPECT_TRUE(idbKeyPath.isValid()); - return createIDBKeyFromScriptValueAndKeyPath(0, value, idbKeyPath); + return createIDBKeyFromScriptValueAndKeyPath(isolate, value, idbKeyPath); } -void checkKeyPathNullValue(const ScriptValue& value, const String& keyPath) +void checkKeyPathNullValue(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath) { - RefPtr<IDBKey> idbKey = checkKeyFromValueAndKeyPathInternal(value, keyPath); - ASSERT_FALSE(idbKey.get()); + ASSERT_FALSE(checkKeyFromValueAndKeyPathInternal(isolate, value, keyPath)); } -bool injectKey(PassRefPtr<IDBKey> key, ScriptValue& value, const String& keyPath) +bool injectKey(ScriptState* scriptState, IDBKey* key, ScriptValue& value, const String& keyPath) { IDBKeyPath idbKeyPath(keyPath); EXPECT_TRUE(idbKeyPath.isValid()); - ScriptValue keyValue = idbKeyToScriptValue(0, key); - return injectV8KeyIntoV8Value(keyValue.v8Value(), value.v8Value(), idbKeyPath, v8::Isolate::GetCurrent()); + ScriptValue keyValue = idbKeyToScriptValue(scriptState, key); + return injectV8KeyIntoV8Value(scriptState->isolate(), keyValue.v8Value(), value.v8Value(), idbKeyPath); } -void checkInjection(PassRefPtr<IDBKey> prpKey, ScriptValue& value, const String& keyPath) +void checkInjection(ScriptState* scriptState, IDBKey* key, ScriptValue& value, const String& keyPath) { - RefPtr<IDBKey> key = prpKey; - bool result = injectKey(key, value, keyPath); + bool result = injectKey(scriptState, key, value, keyPath); ASSERT_TRUE(result); - RefPtr<IDBKey> extractedKey = checkKeyFromValueAndKeyPathInternal(value, keyPath); - EXPECT_TRUE(key->isEqual(extractedKey.get())); + IDBKey* extractedKey = checkKeyFromValueAndKeyPathInternal(scriptState->isolate(), value, keyPath); + EXPECT_TRUE(key->isEqual(extractedKey)); } -void checkInjectionFails(PassRefPtr<IDBKey> key, ScriptValue& value, const String& keyPath) +void checkInjectionFails(ScriptState* scriptState, IDBKey* key, ScriptValue& value, const String& keyPath) { - EXPECT_FALSE(injectKey(key, value, keyPath)); + EXPECT_FALSE(injectKey(scriptState, key, value, keyPath)); } -void checkKeyPathStringValue(const ScriptValue& value, const String& keyPath, const String& expected) +void checkKeyPathStringValue(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath, const String& expected) { - RefPtr<IDBKey> idbKey = checkKeyFromValueAndKeyPathInternal(value, keyPath); - ASSERT_TRUE(idbKey.get()); + IDBKey* idbKey = checkKeyFromValueAndKeyPathInternal(isolate, value, keyPath); + ASSERT_TRUE(idbKey); ASSERT_EQ(IDBKey::StringType, idbKey->type()); ASSERT_TRUE(expected == idbKey->string()); } -void checkKeyPathNumberValue(const ScriptValue& value, const String& keyPath, int expected) +void checkKeyPathNumberValue(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath, int expected) { - RefPtr<IDBKey> idbKey = checkKeyFromValueAndKeyPathInternal(value, keyPath); - ASSERT_TRUE(idbKey.get()); + IDBKey* idbKey = checkKeyFromValueAndKeyPathInternal(isolate, value, keyPath); + ASSERT_TRUE(idbKey); ASSERT_EQ(IDBKey::NumberType, idbKey->type()); ASSERT_TRUE(expected == idbKey->number()); } @@ -93,49 +89,52 @@ void checkKeyPathNumberValue(const ScriptValue& value, const String& keyPath, in class IDBKeyFromValueAndKeyPathTest : public testing::Test { public: IDBKeyFromValueAndKeyPathTest() - : m_handleScope(v8::Isolate::GetCurrent()) - , m_scope(v8::Context::New(v8::Isolate::GetCurrent())) + : m_scope(v8::Isolate::GetCurrent()) { } + ScriptState* scriptState() const { return m_scope.scriptState(); } + private: - v8::HandleScope m_handleScope; - v8::Context::Scope m_scope; + V8TestingScope m_scope; }; TEST_F(IDBKeyFromValueAndKeyPathTest, TopLevelPropertyStringValue) { - v8::Local<v8::Object> object = v8::Object::New(); - object->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "foo"), v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "zoo")); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Object> object = v8::Object::New(isolate); + object->Set(v8AtomicString(isolate, "foo"), v8AtomicString(isolate, "zoo")); - ScriptValue scriptValue(object, v8::Isolate::GetCurrent()); + ScriptValue scriptValue(scriptState(), object); - checkKeyPathStringValue(scriptValue, "foo", "zoo"); - checkKeyPathNullValue(scriptValue, "bar"); + checkKeyPathStringValue(isolate, scriptValue, "foo", "zoo"); + checkKeyPathNullValue(isolate, scriptValue, "bar"); } TEST_F(IDBKeyFromValueAndKeyPathTest, TopLevelPropertyNumberValue) { - v8::Local<v8::Object> object = v8::Object::New(); - object->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "foo"), v8::Number::New(456)); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Object> object = v8::Object::New(isolate); + object->Set(v8AtomicString(isolate, "foo"), v8::Number::New(isolate, 456)); - ScriptValue scriptValue(object, v8::Isolate::GetCurrent()); + ScriptValue scriptValue(scriptState(), object); - checkKeyPathNumberValue(scriptValue, "foo", 456); - checkKeyPathNullValue(scriptValue, "bar"); + checkKeyPathNumberValue(isolate, scriptValue, "foo", 456); + checkKeyPathNullValue(isolate, scriptValue, "bar"); } TEST_F(IDBKeyFromValueAndKeyPathTest, SubProperty) { - v8::Local<v8::Object> object = v8::Object::New(); - v8::Local<v8::Object> subProperty = v8::Object::New(); - subProperty->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "bar"), v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "zee")); - object->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "foo"), subProperty); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Object> object = v8::Object::New(isolate); + v8::Local<v8::Object> subProperty = v8::Object::New(isolate); + subProperty->Set(v8AtomicString(isolate, "bar"), v8AtomicString(isolate, "zee")); + object->Set(v8AtomicString(isolate, "foo"), subProperty); - ScriptValue scriptValue(object, v8::Isolate::GetCurrent()); + ScriptValue scriptValue(scriptState(), object); - checkKeyPathStringValue(scriptValue, "foo.bar", "zee"); - checkKeyPathNullValue(scriptValue, "bar"); + checkKeyPathStringValue(isolate, scriptValue, "foo.bar", "zee"); + checkKeyPathNullValue(isolate, scriptValue, "bar"); } class InjectIDBKeyTest : public IDBKeyFromValueAndKeyPathTest { @@ -143,33 +142,35 @@ class InjectIDBKeyTest : public IDBKeyFromValueAndKeyPathTest { TEST_F(InjectIDBKeyTest, TopLevelPropertyStringValue) { - v8::Local<v8::Object> object = v8::Object::New(); - object->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "foo"), v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "zoo")); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Object> object = v8::Object::New(isolate); + object->Set(v8AtomicString(isolate, "foo"), v8AtomicString(isolate, "zoo")); - ScriptValue foozoo(object, v8::Isolate::GetCurrent()); - checkInjection(IDBKey::createString("myNewKey"), foozoo, "bar"); - checkInjection(IDBKey::createNumber(1234), foozoo, "bar"); + ScriptValue foozoo(scriptState(), object); + checkInjection(scriptState(), IDBKey::createString("myNewKey"), foozoo, "bar"); + checkInjection(scriptState(), IDBKey::createNumber(1234), foozoo, "bar"); - checkInjectionFails(IDBKey::createString("key"), foozoo, "foo.bar"); + checkInjectionFails(scriptState(), IDBKey::createString("key"), foozoo, "foo.bar"); } TEST_F(InjectIDBKeyTest, SubProperty) { - v8::Local<v8::Object> object = v8::Object::New(); - v8::Local<v8::Object> subProperty = v8::Object::New(); - subProperty->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "bar"), v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "zee")); - object->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "foo"), subProperty); - - ScriptValue scriptObject(object, v8::Isolate::GetCurrent()); - checkInjection(IDBKey::createString("myNewKey"), scriptObject, "foo.baz"); - checkInjection(IDBKey::createNumber(789), scriptObject, "foo.baz"); - checkInjection(IDBKey::createDate(4567), scriptObject, "foo.baz"); - checkInjection(IDBKey::createDate(4567), scriptObject, "bar"); - checkInjection(IDBKey::createArray(IDBKey::KeyArray()), scriptObject, "foo.baz"); - checkInjection(IDBKey::createArray(IDBKey::KeyArray()), scriptObject, "bar"); - - checkInjectionFails(IDBKey::createString("zoo"), scriptObject, "foo.bar.baz"); - checkInjection(IDBKey::createString("zoo"), scriptObject, "foo.xyz.foo"); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Object> object = v8::Object::New(isolate); + v8::Local<v8::Object> subProperty = v8::Object::New(isolate); + subProperty->Set(v8AtomicString(isolate, "bar"), v8AtomicString(isolate, "zee")); + object->Set(v8AtomicString(isolate, "foo"), subProperty); + + ScriptValue scriptObject(scriptState(), object); + checkInjection(scriptState(), IDBKey::createString("myNewKey"), scriptObject, "foo.baz"); + checkInjection(scriptState(), IDBKey::createNumber(789), scriptObject, "foo.baz"); + checkInjection(scriptState(), IDBKey::createDate(4567), scriptObject, "foo.baz"); + checkInjection(scriptState(), IDBKey::createDate(4567), scriptObject, "bar"); + checkInjection(scriptState(), IDBKey::createArray(IDBKey::KeyArray()), scriptObject, "foo.baz"); + checkInjection(scriptState(), IDBKey::createArray(IDBKey::KeyArray()), scriptObject, "bar"); + + checkInjectionFails(scriptState(), IDBKey::createString("zoo"), scriptObject, "foo.bar.baz"); + checkInjection(scriptState(), IDBKey::createString("zoo"), scriptObject, "foo.xyz.foo"); } } // namespace diff --git a/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.cpp b/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.cpp index e094bf92563..11f34a44d97 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.cpp @@ -38,8 +38,8 @@ #include "bindings/v8/WrapperTypeInfo.h" #include "bindings/v8/npruntime_impl.h" #include "bindings/v8/npruntime_priv.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" #include "platform/UserGestureIndicator.h" #include "wtf/OwnPtr.h" @@ -53,7 +53,7 @@ namespace WebCore { const WrapperTypeInfo* npObjectTypeInfo() { - static const WrapperTypeInfo typeInfo = { gin::kEmbedderBlink, 0, 0, 0, 0, 0, 0, 0, WrapperTypeObjectPrototype }; + static const WrapperTypeInfo typeInfo = { gin::kEmbedderBlink, 0, 0, 0, 0, 0, 0, 0, WrapperTypeObjectPrototype, RefCountedObject }; return &typeInfo; } @@ -77,14 +77,16 @@ static NPClass V8NPObjectClass = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static v8::Local<v8::Context> toV8Context(NPP npp, NPObject* npObject) +static ScriptState* mainWorldScriptState(v8::Isolate* isolate, NPP npp, NPObject* npObject) { ASSERT(npObject->_class == &V8NPObjectClass); V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); - DOMWindow* window = object->rootObject; + LocalDOMWindow* window = object->rootObject; if (!window || !window->isCurrentlyDisplayedInFrame()) - return v8::Local<v8::Context>(); - return ScriptController::mainWorldContext(object->rootObject->frame()); + return 0; + v8::HandleScope handleScope(isolate); + v8::Handle<v8::Context> context = toV8Context(object->rootObject->frame(), DOMWrapperWorld::mainWorld()); + return ScriptState::from(context); } static PassOwnPtr<v8::Handle<v8::Value>[]> createValueListFromVariantArgs(const NPVariant* arguments, uint32_t argumentCount, NPObject* owner, v8::Isolate* isolate) @@ -114,7 +116,7 @@ NPObject* v8ObjectToNPObject(v8::Handle<v8::Object> object) return reinterpret_cast<NPObject*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); } -NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, DOMWindow* root, v8::Isolate* isolate) +NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, LocalDOMWindow* root, v8::Isolate* isolate) { // Check to see if this object is already wrapped. if (object->InternalFieldCount() == npObjectInternalFieldCount) { @@ -141,10 +143,10 @@ NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, DOMWind return reinterpret_cast<NPObject*>(v8npObject); } } + objectVector = &iter->value; } else { - iter = v8NPObjectMap->set(v8ObjectHash, V8NPObjectVector()).iterator; + objectVector = &v8NPObjectMap->set(v8ObjectHash, V8NPObjectVector()).storedValue->value; } - objectVector = &iter->value; } V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass)); @@ -230,13 +232,12 @@ bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPV return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result); } - v8::HandleScope handleScope(isolate); // FIXME: should use the plugin's owner frame as the security context. - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NpObject->v8Object); @@ -250,7 +251,7 @@ bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPV return false; } - Frame* frame = v8NpObject->rootObject->frame(); + LocalFrame* frame = v8NpObject->rootObject->frame(); ASSERT(frame); // Call the function object. @@ -286,12 +287,11 @@ bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments, VOID_TO_NPVARIANT(*result); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; // Lookup the function object and call it. @@ -302,7 +302,7 @@ bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments, v8::Local<v8::Value> resultObject; v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(functionObject); if (!function->IsNull()) { - Frame* frame = v8NpObject->rootObject->frame(); + LocalFrame* frame = v8NpObject->rootObject->frame(); ASSERT(frame); OwnPtr<v8::Handle<v8::Value>[]> argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate); @@ -335,12 +335,11 @@ bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPStri return false; v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; // FIXME: Is this branch still needed after switching to using UserGestureIndicator? @@ -348,13 +347,13 @@ bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPStri if (!popupsAllowed) filename = "npscript"; - Frame* frame = v8NpObject->rootObject->frame(); + LocalFrame* frame = v8NpObject->rootObject->frame(); ASSERT(frame); String script = String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length); UserGestureIndicator gestureIndicator(popupsAllowed ? DefinitelyProcessingNewUserGesture : PossiblyProcessingUserGesture); - v8::Local<v8::Value> v8result = frame->script().executeScriptAndReturnValue(context, ScriptSourceCode(script, KURL(ParsedURLString, filename))); + v8::Local<v8::Value> v8result = frame->script().executeScriptAndReturnValue(scriptState->context(), ScriptSourceCode(script, KURL(ParsedURLString, filename))); if (v8result.IsEmpty()) return false; @@ -371,12 +370,11 @@ bool _NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NP if (V8NPObject* object = npObjectToV8NPObject(npObject)) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); @@ -405,16 +403,15 @@ bool _NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, co if (V8NPObject* object = npObjectToV8NPObject(npObject)) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); - obj->Set(npIdentifierToV8Identifier(propertyName, context->GetIsolate()), convertNPVariantToV8Object(value, object->rootObject->frame()->script().windowScriptNPObject(), context->GetIsolate())); + obj->Set(npIdentifierToV8Identifier(propertyName, isolate), convertNPVariantToV8Object(value, object->rootObject->frame()->script().windowScriptNPObject(), isolate)); return true; } @@ -434,11 +431,10 @@ bool _NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) return false; v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); @@ -454,11 +450,10 @@ bool _NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) if (V8NPObject* object = npObjectToV8NPObject(npObject)) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); @@ -477,11 +472,10 @@ bool _NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName) if (V8NPObject* object = npObjectToV8NPObject(npObject)) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); @@ -503,15 +497,15 @@ void _NPN_SetException(NPObject* npObject, const NPUTF8 *message) return; } - v8::HandleScope handleScope(v8::Isolate::GetCurrent()); - v8::Handle<v8::Context> context = toV8Context(0, npObject); - if (context.IsEmpty()) + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + ScriptState* scriptState = mainWorldScriptState(isolate, 0, npObject); + if (!scriptState) return; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; - throwError(v8GeneralError, message, context->GetIsolate()); + throwError(v8GeneralError, message, isolate); } bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint32_t* count) @@ -521,11 +515,10 @@ bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint if (V8NPObject* object = npObjectToV8NPObject(npObject)) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Local<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); @@ -542,22 +535,22 @@ bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint " }" " return props;" "});"; - v8::Handle<v8::String> source = v8::String::NewFromUtf8(isolate, enumeratorCode); - v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(source, context->GetIsolate()); + v8::Handle<v8::String> source = v8AtomicString(isolate, enumeratorCode); + v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(source, isolate); ASSERT(!result.IsEmpty()); ASSERT(result->IsFunction()); v8::Handle<v8::Function> enumerator = v8::Handle<v8::Function>::Cast(result); v8::Handle<v8::Value> argv[] = { obj }; - v8::Local<v8::Value> propsObj = V8ScriptRunner::callInternalFunction(enumerator, v8::Handle<v8::Object>::Cast(result), WTF_ARRAY_LENGTH(argv), argv, context->GetIsolate()); + v8::Local<v8::Value> propsObj = V8ScriptRunner::callInternalFunction(enumerator, v8::Handle<v8::Object>::Cast(result), WTF_ARRAY_LENGTH(argv), argv, isolate); if (propsObj.IsEmpty()) return false; // Convert the results into an array of NPIdentifiers. v8::Handle<v8::Array> props = v8::Handle<v8::Array>::Cast(propsObj); *count = props->Length(); - *identifier = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier*) * *count)); + *identifier = static_cast<NPIdentifier*>(calloc(*count, sizeof(NPIdentifier))); for (uint32_t i = 0; i < *count; ++i) { - v8::Local<v8::Value> name = props->Get(v8::Integer::New(i, context->GetIsolate())); + v8::Local<v8::Value> name = props->Get(v8::Integer::New(isolate, i)); (*identifier)[i] = getStringIdentifier(v8::Local<v8::String>::Cast(name)); } return true; @@ -577,11 +570,10 @@ bool _NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uin v8::Isolate* isolate = v8::Isolate::GetCurrent(); if (V8NPObject* object = npObjectToV8NPObject(npObject)) { - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; // Lookup the constructor function. @@ -593,10 +585,10 @@ bool _NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uin v8::Local<v8::Value> resultObject; v8::Handle<v8::Function> ctor = v8::Handle<v8::Function>::Cast(ctorObj); if (!ctor->IsNull()) { - Frame* frame = object->rootObject->frame(); + LocalFrame* frame = object->rootObject->frame(); ASSERT(frame); OwnPtr<v8::Handle<v8::Value>[]> argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate); - resultObject = V8ObjectConstructor::newInstanceInDocument(ctor, argumentCount, argv.get(), frame ? frame->document() : 0); + resultObject = V8ObjectConstructor::newInstanceInDocument(isolate, ctor, argumentCount, argv.get(), frame ? frame->document() : 0); } if (resultObject.IsEmpty()) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.h b/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.h index 435f778d151..3e7db341956 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.h @@ -39,7 +39,7 @@ namespace WebCore { -class DOMWindow; +class LocalDOMWindow; static const int npObjectInternalFieldCount = v8DefaultWrapperInternalFieldCount + 0; @@ -53,7 +53,7 @@ struct V8NPObject { public: NPObject object; v8::Persistent<v8::Object> v8Object; - DOMWindow* rootObject; + LocalDOMWindow* rootObject; }; struct PrivateIdentifier { @@ -64,7 +64,7 @@ struct PrivateIdentifier { bool isString; }; -NPObject* npCreateV8ScriptObject(NPP, v8::Handle<v8::Object>, DOMWindow*, v8::Isolate*); +NPObject* npCreateV8ScriptObject(NPP, v8::Handle<v8::Object>, LocalDOMWindow*, v8::Isolate*); NPObject* v8ObjectToNPObject(v8::Handle<v8::Object>); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/Nullable.h b/chromium/third_party/WebKit/Source/bindings/v8/Nullable.h new file mode 100644 index 00000000000..0f8356c472d --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/Nullable.h @@ -0,0 +1,51 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef Nullable_h +#define Nullable_h + +#include "wtf/Assertions.h" + +namespace WebCore { + +template <typename T> +class Nullable { +public: + Nullable() + : m_value() + , m_isNull(true) { } + + Nullable(const T& value) + : m_value(value) + , m_isNull(false) { } + + Nullable(const Nullable& other) + : m_value(other.m_value) + , m_isNull(other.m_isNull) { } + + Nullable& operator=(const Nullable& other) + { + m_value = other.m_value; + m_isNull = other.m_isNull; + return *this; + } + + T get() const { ASSERT(!m_isNull); return m_value; } + bool isNull() const { return m_isNull; } + + operator bool() const { return !m_isNull && m_value; } + + bool operator==(const Nullable& other) const + { + return (m_isNull && other.m_isNull) || (!m_isNull && !other.m_isNull && m_value == other.m_value); + } + +private: + T m_value; + bool m_isNull; +}; + +} // namespace WebCore + +#endif // Nullable_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.cpp b/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.cpp index 44a2b48a22c..5901fba1eaf 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.cpp @@ -32,15 +32,20 @@ #include "bindings/v8/PageScriptDebugServer.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Window.h" +#include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/ScriptSourceCode.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ScriptRunner.h" #include "bindings/v8/V8WindowShell.h" +#include "core/frame/FrameConsole.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/UseCounter.h" #include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/inspector/ScriptDebugListener.h" -#include "core/frame/Frame.h" #include "core/page/Page.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" @@ -50,17 +55,20 @@ namespace WebCore { -static Frame* retrieveFrameWithGlobalObjectCheck(v8::Handle<v8::Context> context) +static LocalFrame* retrieveFrameWithGlobalObjectCheck(v8::Handle<v8::Context> context) { if (context.IsEmpty()) return 0; - // Test that context has associated global dom window object. - v8::Handle<v8::Object> global = context->Global(); - if (global.IsEmpty()) + // FIXME: This is a temporary hack for crbug.com/345014. + // Currently it's possible that V8 can trigger Debugger::ProcessDebugEvent for a context + // that is being initialized (i.e., inside Context::New() of the context). + // We should fix the V8 side so that it won't trigger the event for a half-baked context + // because there is no way in the embedder side to check if the context is half-baked or not. + if (isMainThread() && DOMWrapperWorld::windowIsBeingInitialized()) return 0; - global = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), worldTypeInMainThread(context->GetIsolate()))); + v8::Handle<v8::Value> global = V8Window::findInstanceInPrototypeChain(context->Global(), context->GetIsolate()); if (global.IsEmpty()) return 0; @@ -82,31 +90,44 @@ PageScriptDebugServer& PageScriptDebugServer::shared() return server; } +v8::Isolate* PageScriptDebugServer::s_mainThreadIsolate = 0; + +void PageScriptDebugServer::setMainThreadIsolate(v8::Isolate* isolate) +{ + s_mainThreadIsolate = isolate; +} + PageScriptDebugServer::PageScriptDebugServer() - : ScriptDebugServer(v8::Isolate::GetCurrent()) + : ScriptDebugServer(s_mainThreadIsolate) , m_pausedPage(0) { } +PageScriptDebugServer::~PageScriptDebugServer() +{ +} + void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) { - ScriptController& scriptController = page->mainFrame()->script(); + ScriptController& scriptController = page->deprecatedLocalMainFrame()->script(); if (!scriptController.canExecuteScripts(NotAboutToExecuteScript)) return; v8::HandleScope scope(m_isolate); - v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); - v8::Context::Scope contextScope(debuggerContext); - v8::Local<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isolate); if (!m_listenersMap.size()) { + v8::Debug::SetDebugEventListener(&PageScriptDebugServer::v8DebugEventCallback, v8::External::New(m_isolate, this)); ensureDebuggerScriptCompiled(); - ASSERT(!debuggerScript->IsUndefined()); - v8::Debug::SetDebugEventListener2(&PageScriptDebugServer::v8DebugEventCallback, v8::External::New(m_isolate, this)); } + + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + v8::Local<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isolate); + ASSERT(!debuggerScript->IsUndefined()); m_listenersMap.set(page, listener); - V8WindowShell* shell = scriptController.existingWindowShell(mainThreadNormalWorld()); + V8WindowShell* shell = scriptController.existingWindowShell(DOMWrapperWorld::mainWorld()); if (!shell || !shell->isContextInitialized()) return; v8::Local<v8::Context> context = shell->context(); @@ -118,7 +139,7 @@ void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* pag ASSERT(!value->IsUndefined() && value->IsArray()); v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value); for (unsigned i = 0; i < scriptsArray->Length(); ++i) - dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i, m_isolate)))); + dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(m_isolate, i)))); } void PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) @@ -131,9 +152,16 @@ void PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* m_listenersMap.remove(page); - if (m_listenersMap.isEmpty()) - v8::Debug::SetDebugEventListener2(0); - // FIXME: Remove all breakpoints set by the agent. + if (m_listenersMap.isEmpty()) { + discardDebuggerScript(); + v8::Debug::SetDebugEventListener(0); + // FIXME: Remove all breakpoints set by the agent. + } +} + +void PageScriptDebugServer::interruptAndRun(PassOwnPtr<Task> task) +{ + ScriptDebugServer::interruptAndRun(task, s_mainThreadIsolate); } void PageScriptDebugServer::setClientMessageLoop(PassOwnPtr<ClientMessageLoop> clientMessageLoop) @@ -141,11 +169,11 @@ void PageScriptDebugServer::setClientMessageLoop(PassOwnPtr<ClientMessageLoop> c m_clientMessageLoop = clientMessageLoop; } -void PageScriptDebugServer::compileScript(ScriptState* state, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage) +void PageScriptDebugServer::compileScript(ScriptState* scriptState, const String& expression, const String& sourceURL, String* scriptId, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) { - ExecutionContext* executionContext = state->executionContext(); - RefPtr<Frame> protect = toDocument(executionContext)->frame(); - ScriptDebugServer::compileScript(state, expression, sourceURL, scriptId, exceptionMessage); + ExecutionContext* executionContext = scriptState->executionContext(); + RefPtr<LocalFrame> protect = toDocument(executionContext)->frame(); + ScriptDebugServer::compileScript(scriptState, expression, sourceURL, scriptId, exceptionDetailsText, lineNumber, columnNumber, stackTrace); if (!scriptId->isNull()) m_compiledScriptURLs.set(*scriptId, sourceURL); } @@ -156,27 +184,31 @@ void PageScriptDebugServer::clearCompiledScripts() m_compiledScriptURLs.clear(); } -void PageScriptDebugServer::runScript(ScriptState* state, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage) +void PageScriptDebugServer::runScript(ScriptState* scriptState, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) { String sourceURL = m_compiledScriptURLs.take(scriptId); - ExecutionContext* executionContext = state->executionContext(); - Frame* frame = toDocument(executionContext)->frame(); + ExecutionContext* executionContext = scriptState->executionContext(); + LocalFrame* frame = toDocument(executionContext)->frame(); + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EvaluateScript", "data", InspectorEvaluateScriptEvent::data(frame, sourceURL, TextPosition::minimumPosition().m_line.oneBasedInt())); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie; if (frame) cookie = InspectorInstrumentation::willEvaluateScript(frame, sourceURL, TextPosition::minimumPosition().m_line.oneBasedInt()); - RefPtr<Frame> protect = frame; - ScriptDebugServer::runScript(state, scriptId, result, wasThrown, exceptionMessage); + RefPtr<LocalFrame> protect = frame; + ScriptDebugServer::runScript(scriptState, scriptId, result, wasThrown, exceptionDetailsText, lineNumber, columnNumber, stackTrace); if (frame) InspectorInstrumentation::didEvaluateScript(cookie); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); } ScriptDebugListener* PageScriptDebugServer::getDebugListenerForContext(v8::Handle<v8::Context> context) { v8::HandleScope scope(m_isolate); - Frame* frame = retrieveFrameWithGlobalObjectCheck(context); + LocalFrame* frame = retrieveFrameWithGlobalObjectCheck(context); if (!frame) return 0; return m_listenersMap.get(frame->page()); @@ -185,7 +217,7 @@ ScriptDebugListener* PageScriptDebugServer::getDebugListenerForContext(v8::Handl void PageScriptDebugServer::runMessageLoopOnPause(v8::Handle<v8::Context> context) { v8::HandleScope scope(m_isolate); - Frame* frame = retrieveFrameWithGlobalObjectCheck(context); + LocalFrame* frame = retrieveFrameWithGlobalObjectCheck(context); m_pausedPage = frame->page(); // Wait for continue or step command. @@ -206,7 +238,7 @@ void PageScriptDebugServer::quitMessageLoopOnPause() void PageScriptDebugServer::preprocessBeforeCompile(const v8::Debug::EventDetails& eventDetails) { v8::Handle<v8::Context> eventContext = eventDetails.GetEventContext(); - Frame* frame = retrieveFrameWithGlobalObjectCheck(eventContext); + LocalFrame* frame = retrieveFrameWithGlobalObjectCheck(eventContext); if (!frame) return; @@ -236,7 +268,7 @@ void PageScriptDebugServer::preprocessBeforeCompile(const v8::Debug::EventDetail static bool isCreatingPreprocessor = false; -bool PageScriptDebugServer::canPreprocess(Frame* frame) +bool PageScriptDebugServer::canPreprocess(LocalFrame* frame) { ASSERT(frame); @@ -247,7 +279,7 @@ bool PageScriptDebugServer::canPreprocess(Frame* frame) // Web page to ensure that the debugger's console initialization code has completed. if (!m_scriptPreprocessor) { TemporaryChange<bool> isPreprocessing(isCreatingPreprocessor, true); - m_scriptPreprocessor = adoptPtr(new ScriptPreprocessor(*m_preprocessorSourceCode.get(), frame->script(), frame->page()->console())); + m_scriptPreprocessor = adoptPtr(new ScriptPreprocessor(*m_preprocessorSourceCode.get(), frame)); } if (m_scriptPreprocessor->isValid()) @@ -260,7 +292,7 @@ bool PageScriptDebugServer::canPreprocess(Frame* frame) } // Source to Source processing iff debugger enabled and it has loaded a preprocessor. -PassOwnPtr<ScriptSourceCode> PageScriptDebugServer::preprocess(Frame* frame, const ScriptSourceCode& sourceCode) +PassOwnPtr<ScriptSourceCode> PageScriptDebugServer::preprocess(LocalFrame* frame, const ScriptSourceCode& sourceCode) { if (!canPreprocess(frame)) return PassOwnPtr<ScriptSourceCode>(); @@ -269,7 +301,7 @@ PassOwnPtr<ScriptSourceCode> PageScriptDebugServer::preprocess(Frame* frame, con return adoptPtr(new ScriptSourceCode(preprocessedSource, sourceCode.url())); } -String PageScriptDebugServer::preprocessEventListener(Frame* frame, const String& source, const String& url, const String& functionName) +String PageScriptDebugServer::preprocessEventListener(LocalFrame* frame, const String& source, const String& url, const String& functionName) { if (!canPreprocess(frame)) return source; @@ -277,4 +309,16 @@ String PageScriptDebugServer::preprocessEventListener(Frame* frame, const String return m_scriptPreprocessor->preprocessSourceCode(source, url, functionName); } +void PageScriptDebugServer::muteWarningsAndDeprecations() +{ + FrameConsole::mute(); + UseCounter::muteForInspector(); +} + +void PageScriptDebugServer::unmuteWarningsAndDeprecations() +{ + FrameConsole::unmute(); + UseCounter::unmuteForInspector(); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.h b/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.h index 78fde09e688..96f8779f223 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.h @@ -31,11 +31,11 @@ #ifndef PageScriptDebugServer_h #define PageScriptDebugServer_h - #include "bindings/v8/ScriptDebugServer.h" #include "bindings/v8/ScriptPreprocessor.h" #include "wtf/Forward.h" #include "wtf/RefCounted.h" +#include <v8.h> namespace WebCore { @@ -44,14 +44,18 @@ class ScriptController; class ScriptPreprocessor; class ScriptSourceCode; -class PageScriptDebugServer : public ScriptDebugServer { +class PageScriptDebugServer FINAL : public ScriptDebugServer { WTF_MAKE_NONCOPYABLE(PageScriptDebugServer); public: static PageScriptDebugServer& shared(); + static void setMainThreadIsolate(v8::Isolate*); + void addListener(ScriptDebugListener*, Page*); void removeListener(ScriptDebugListener*, Page*); + static void interruptAndRun(PassOwnPtr<Task>); + class ClientMessageLoop { public: virtual ~ClientMessageLoop() { } @@ -60,21 +64,24 @@ public: }; void setClientMessageLoop(PassOwnPtr<ClientMessageLoop>); - virtual void compileScript(ScriptState*, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage); - virtual void clearCompiledScripts(); - virtual void runScript(ScriptState*, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage); - virtual void setPreprocessorSource(const String&); - virtual void preprocessBeforeCompile(const v8::Debug::EventDetails&); - virtual PassOwnPtr<ScriptSourceCode> preprocess(Frame*, const ScriptSourceCode&); - virtual String preprocessEventListener(Frame*, const String& source, const String& url, const String& functionName); + virtual void compileScript(ScriptState*, const String& expression, const String& sourceURL, String* scriptId, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) OVERRIDE; + virtual void clearCompiledScripts() OVERRIDE; + virtual void runScript(ScriptState*, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) OVERRIDE; + virtual void setPreprocessorSource(const String&) OVERRIDE; + virtual void preprocessBeforeCompile(const v8::Debug::EventDetails&) OVERRIDE; + virtual PassOwnPtr<ScriptSourceCode> preprocess(LocalFrame*, const ScriptSourceCode&) OVERRIDE; + virtual String preprocessEventListener(LocalFrame*, const String& source, const String& url, const String& functionName) OVERRIDE; + + virtual void muteWarningsAndDeprecations() OVERRIDE; + virtual void unmuteWarningsAndDeprecations() OVERRIDE; private: PageScriptDebugServer(); - virtual ~PageScriptDebugServer() { } + virtual ~PageScriptDebugServer(); - virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>); - virtual void runMessageLoopOnPause(v8::Handle<v8::Context>); - virtual void quitMessageLoopOnPause(); + virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>) OVERRIDE; + virtual void runMessageLoopOnPause(v8::Handle<v8::Context>) OVERRIDE; + virtual void quitMessageLoopOnPause() OVERRIDE; typedef HashMap<Page*, ScriptDebugListener*> ListenersMap; ListenersMap m_listenersMap; @@ -84,7 +91,8 @@ private: OwnPtr<ScriptSourceCode> m_preprocessorSourceCode; OwnPtr<ScriptPreprocessor> m_scriptPreprocessor; - bool canPreprocess(Frame*); + bool canPreprocess(LocalFrame*); + static v8::Isolate* s_mainThreadIsolate; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/RetainedDOMInfo.h b/chromium/third_party/WebKit/Source/bindings/v8/RetainedDOMInfo.h index 52709997cfc..2138c0b9937 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/RetainedDOMInfo.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/RetainedDOMInfo.h @@ -32,23 +32,24 @@ #define RetainedDOMInfo_h #include "bindings/v8/RetainedObjectInfo.h" +#include <v8-profiler.h> namespace WebCore { class Node; // Implements v8::RetainedObjectInfo. -class RetainedDOMInfo : public RetainedObjectInfo { +class RetainedDOMInfo FINAL : public RetainedObjectInfo { public: explicit RetainedDOMInfo(Node* root); virtual ~RetainedDOMInfo(); - virtual void Dispose(); - virtual bool IsEquivalent(v8::RetainedObjectInfo* other); - virtual intptr_t GetHash(); - virtual const char* GetGroupLabel(); - virtual const char* GetLabel(); - virtual intptr_t GetElementCount(); - virtual intptr_t GetEquivalenceClass(); + virtual void Dispose() OVERRIDE; + virtual bool IsEquivalent(v8::RetainedObjectInfo* other) OVERRIDE; + virtual intptr_t GetHash() OVERRIDE; + virtual const char* GetGroupLabel() OVERRIDE; + virtual const char* GetLabel() OVERRIDE; + virtual intptr_t GetElementCount() OVERRIDE; + virtual intptr_t GetEquivalenceClass() OVERRIDE; private: // V8 guarantees to keep RetainedObjectInfos alive only during a GC or heap snapshotting round, when renderer diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.cpp index 1de2039ec15..0f669f310e8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.cpp @@ -38,41 +38,39 @@ #include "bindings/v8/V8ScriptRunner.h" #include "core/dom/Document.h" #include "core/dom/ExecutionContext.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/workers/WorkerGlobalScope.h" #include "core/workers/WorkerThread.h" #include "platform/TraceEvent.h" namespace WebCore { -ScheduledAction::ScheduledAction(v8::Handle<v8::Context> context, v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[], v8::Isolate* isolate) - : m_context(isolate, context) +ScheduledAction::ScheduledAction(ScriptState* scriptState, v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[], v8::Isolate* isolate) + : m_scriptState(scriptState) , m_function(isolate, function) + , m_info(isolate) , m_code(String(), KURL(), TextPosition::belowRangePosition()) - , m_isolate(isolate) { - m_info.reserveCapacity(argc); + m_info.ReserveCapacity(argc); for (int i = 0; i < argc; ++i) - m_info.append(UnsafePersistent<v8::Value>(m_isolate, argv[i])); + m_info.Append(argv[i]); } -ScheduledAction::ScheduledAction(v8::Handle<v8::Context> context, const String& code, const KURL& url, v8::Isolate* isolate) - : m_context(isolate, context) +ScheduledAction::ScheduledAction(ScriptState* scriptState, const String& code, const KURL& url, v8::Isolate* isolate) + : m_scriptState(scriptState) + , m_info(isolate) , m_code(code, url) - , m_isolate(isolate) { } ScheduledAction::~ScheduledAction() { - for (size_t i = 0; i < m_info.size(); ++i) - m_info[i].dispose(); } void ScheduledAction::execute(ExecutionContext* context) { if (context->isDocument()) { - Frame* frame = toDocument(context)->frame(); + LocalFrame* frame = toDocument(context)->frame(); if (!frame) return; if (!frame->script().canExecuteScripts(AboutToExecuteScript)) @@ -83,23 +81,19 @@ void ScheduledAction::execute(ExecutionContext* context) } } -void ScheduledAction::execute(Frame* frame) +void ScheduledAction::execute(LocalFrame* frame) { - v8::HandleScope handleScope(m_isolate); - - v8::Handle<v8::Context> context = m_context.newLocal(m_isolate); - if (context.IsEmpty()) + if (m_scriptState->contextIsEmpty()) return; TRACE_EVENT0("v8", "ScheduledAction::execute"); - + ScriptState::Scope scope(m_scriptState.get()); if (!m_function.isEmpty()) { - v8::Context::Scope scope(context); Vector<v8::Handle<v8::Value> > info; createLocalHandlesForArgs(&info); - frame->script().callFunction(m_function.newLocal(m_isolate), context->Global(), info.size(), info.data()); + frame->script().callFunction(m_function.newLocal(m_scriptState->isolate()), m_scriptState->context()->Global(), info.size(), info.data()); } else { - frame->script().executeScriptAndReturnValue(context, ScriptSourceCode(m_code)); + frame->script().executeScriptAndReturnValue(m_scriptState->context(), ScriptSourceCode(m_code)); } // The frame might be invalid at this point because JavaScript could have released it. @@ -108,23 +102,22 @@ void ScheduledAction::execute(Frame* frame) void ScheduledAction::execute(WorkerGlobalScope* worker) { ASSERT(worker->thread()->isCurrentThread()); - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> context = m_context.newLocal(m_isolate); - ASSERT(!context.IsEmpty()); - v8::Context::Scope scope(context); + ASSERT(!m_scriptState->contextIsEmpty()); if (!m_function.isEmpty()) { + ScriptState::Scope scope(m_scriptState.get()); Vector<v8::Handle<v8::Value> > info; createLocalHandlesForArgs(&info); - V8ScriptRunner::callFunction(m_function.newLocal(m_isolate), worker, context->Global(), info.size(), info.data(), m_isolate); - } else + V8ScriptRunner::callFunction(m_function.newLocal(m_scriptState->isolate()), worker, m_scriptState->context()->Global(), info.size(), info.data(), m_scriptState->isolate()); + } else { worker->script()->evaluate(m_code); + } } void ScheduledAction::createLocalHandlesForArgs(Vector<v8::Handle<v8::Value> >* handles) { - handles->reserveCapacity(m_info.size()); - for (size_t i = 0; i < m_info.size(); ++i) - handles->append(m_info[i].newLocal(m_isolate)); + handles->reserveCapacity(m_info.Size()); + for (size_t i = 0; i < m_info.Size(); ++i) + handles->append(m_info.Get(i)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.h b/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.h index 9b03a027305..351ef3bed7e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.h @@ -33,36 +33,35 @@ #include "bindings/v8/ScopedPersistent.h" #include "bindings/v8/ScriptSourceCode.h" -#include "bindings/v8/UnsafePersistent.h" +#include "bindings/v8/ScriptState.h" +#include "bindings/v8/V8PersistentValueVector.h" #include <v8.h> #include "wtf/Forward.h" -#include "wtf/Vector.h" namespace WebCore { -class Frame; +class LocalFrame; class ExecutionContext; class WorkerGlobalScope; class ScheduledAction { WTF_MAKE_NONCOPYABLE(ScheduledAction); public: - ScheduledAction(v8::Handle<v8::Context>, v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[], v8::Isolate*); - ScheduledAction(v8::Handle<v8::Context>, const String&, const KURL&, v8::Isolate*); + ScheduledAction(ScriptState*, v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[], v8::Isolate*); + ScheduledAction(ScriptState*, const String&, const KURL&, v8::Isolate*); ~ScheduledAction(); void execute(ExecutionContext*); private: - void execute(Frame*); + void execute(LocalFrame*); void execute(WorkerGlobalScope*); void createLocalHandlesForArgs(Vector<v8::Handle<v8::Value> >* handles); - ScopedPersistent<v8::Context> m_context; + ScriptStateProtectingContext m_scriptState; ScopedPersistent<v8::Function> m_function; - Vector<UnsafePersistent<v8::Value> > m_info; + V8PersistentValueVector<v8::Value> m_info; ScriptSourceCode m_code; - v8::Isolate* m_isolate; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScopedPersistent.h b/chromium/third_party/WebKit/Source/bindings/v8/ScopedPersistent.h index 84b6beea6ce..a383f780c37 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScopedPersistent.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScopedPersistent.h @@ -64,6 +64,7 @@ public: } bool isEmpty() const { return m_handle.IsEmpty(); } + bool isWeak() const { return m_handle.IsWeak(); } void set(v8::Isolate* isolate, v8::Handle<T> handle) { @@ -81,6 +82,12 @@ public: return m_handle == other.m_handle; } + template <class S> + bool operator==(const v8::Handle<S> other) const + { + return m_handle == other; + } + private: // FIXME: This function does an unsafe handle access. Remove it. friend class V8AbstractEventListener; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.cpp index 81dea4584c6..8c68a9ddd4a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.cpp @@ -31,10 +31,8 @@ #include "config.h" #include "bindings/v8/ScriptCallStackFactory.h" -#include "bindings/v8/ScriptScope.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "core/inspector/InspectorInstrumentation.h" #include "core/inspector/ScriptArguments.h" #include "core/inspector/ScriptCallFrame.h" @@ -86,7 +84,7 @@ static void toScriptCallFramesVector(v8::Handle<v8::StackTrace> stackTrace, Vect } } -static PassRefPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, bool emptyStackIsAllowed, v8::Isolate* isolate) +static PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, bool emptyStackIsAllowed, v8::Isolate* isolate) { ASSERT(isolate->InContext()); v8::HandleScope scope(isolate); @@ -95,44 +93,38 @@ static PassRefPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTra return ScriptCallStack::create(scriptCallFrames); } -PassRefPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, v8::Isolate* isolate) { return createScriptCallStack(stackTrace, maxStackSize, true, isolate); } -PassRefPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed) +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); if (!isolate->InContext()) - return 0; + return nullptr; v8::HandleScope handleScope(isolate); v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTrace(isolate, maxStackSize, stackTraceOptions)); return createScriptCallStack(stackTrace, maxStackSize, emptyStackIsAllowed, isolate); } -PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(size_t maxStackSize) +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStackForConsole(ScriptState* scriptState, size_t maxStackSize) { size_t stackSize = 1; if (InspectorInstrumentation::hasFrontends()) { - ExecutionContext* executionContext = getExecutionContext(); - if (InspectorInstrumentation::consoleAgentEnabled(executionContext)) + if (InspectorInstrumentation::consoleAgentEnabled(scriptState->executionContext())) stackSize = maxStackSize; } return createScriptCallStack(stackSize); } -PassRefPtr<ScriptArguments> createScriptArguments(const v8::FunctionCallbackInfo<v8::Value>& v8arguments, unsigned skipArgumentCount) +PassRefPtrWillBeRawPtr<ScriptArguments> createScriptArguments(ScriptState* scriptState, const v8::FunctionCallbackInfo<v8::Value>& v8arguments, unsigned skipArgumentCount) { - v8::Isolate* isolate = v8arguments.GetIsolate(); - v8::HandleScope scope(isolate); - v8::Local<v8::Context> context = isolate->GetCurrentContext(); - ScriptState* state = ScriptState::forContext(context); - Vector<ScriptValue> arguments; for (int i = skipArgumentCount; i < v8arguments.Length(); ++i) - arguments.append(ScriptValue(v8arguments[i], isolate)); + arguments.append(ScriptValue(scriptState, v8arguments[i])); - return ScriptArguments::create(state, arguments); + return ScriptArguments::create(scriptState, arguments); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.h index ff225e30714..6654b67aab6 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.h @@ -48,10 +48,10 @@ const v8::StackTrace::StackTraceOptions stackTraceOptions = static_cast<v8::Stac | v8::StackTrace::kScriptNameOrSourceURL | v8::StackTrace::kFunctionName); -PassRefPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace>, size_t maxStackSize, v8::Isolate*); -PassRefPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed = false); -PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(size_t maxStackSize = ScriptCallStack::maxCallStackSizeToCapture); -PassRefPtr<ScriptArguments> createScriptArguments(const v8::FunctionCallbackInfo<v8::Value>& v8arguments, unsigned skipArgumentCount); +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace>, size_t maxStackSize, v8::Isolate*); +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed = false); +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStackForConsole(ScriptState*, size_t maxStackSize = ScriptCallStack::maxCallStackSizeToCapture); +PassRefPtrWillBeRawPtr<ScriptArguments> createScriptArguments(ScriptState*, const v8::FunctionCallbackInfo<v8::Value>& v8arguments, unsigned skipArgumentCount); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.cpp index b60a5c74cca..d7049069670 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.cpp @@ -32,9 +32,9 @@ #include "config.h" #include "bindings/v8/ScriptController.h" -#include "V8Event.h" -#include "V8HTMLElement.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Event.h" +#include "bindings/core/v8/V8HTMLElement.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/BindingSecurity.h" #include "bindings/v8/NPV8Object.h" #include "bindings/v8/ScriptCallStackFactory.h" @@ -42,7 +42,6 @@ #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8GCController.h" -#include "bindings/v8/V8HiddenPropertyName.h" #include "bindings/v8/V8NPObject.h" #include "bindings/v8/V8PerContextData.h" #include "bindings/v8/V8ScriptRunner.h" @@ -54,17 +53,17 @@ #include "core/dom/ScriptableDocumentParser.h" #include "core/events/Event.h" #include "core/events/EventListener.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/html/HTMLPlugInElement.h" #include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/inspector/ScriptCallStack.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" -#include "core/frame/Settings.h" #include "core/plugins/PluginView.h" #include "platform/NotImplemented.h" #include "platform/TraceEvent.h" @@ -81,23 +80,27 @@ namespace WebCore { -bool ScriptController::canAccessFromCurrentOrigin(Frame *frame) +bool ScriptController::canAccessFromCurrentOrigin(LocalFrame *frame) { - return !v8::Isolate::GetCurrent()->InContext() || BindingSecurity::shouldAllowAccessToFrame(frame); + if (!frame) + return false; + v8::Isolate* isolate = toIsolate(frame); + return !isolate->InContext() || BindingSecurity::shouldAllowAccessToFrame(isolate, frame); } -ScriptController::ScriptController(Frame* frame) +ScriptController::ScriptController(LocalFrame* frame) : m_frame(frame) , m_sourceURL(0) , m_isolate(v8::Isolate::GetCurrent()) - , m_windowShell(V8WindowShell::create(frame, mainThreadNormalWorld(), m_isolate)) + , m_windowShell(V8WindowShell::create(frame, DOMWrapperWorld::mainWorld(), m_isolate)) , m_windowScriptNPObject(0) { } ScriptController::~ScriptController() { - clearForClose(true); + // V8WindowShell::clearForClose() must be invoked before destruction starts. + ASSERT(!m_windowShell->isContextInitialized()); } void ScriptController::clearScriptObjects() @@ -120,61 +123,39 @@ void ScriptController::clearScriptObjects() } } -void ScriptController::clearForOutOfMemory() -{ - clearForClose(true); -} - -void ScriptController::clearForClose(bool destroyGlobal) -{ - m_windowShell->clearForClose(destroyGlobal); - for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin(); iter != m_isolatedWorlds.end(); ++iter) - iter->value->clearForClose(destroyGlobal); - V8GCController::hintForCollectGarbage(); -} - void ScriptController::clearForClose() { double start = currentTime(); - clearForClose(false); + m_windowShell->clearForClose(); + for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin(); iter != m_isolatedWorlds.end(); ++iter) + iter->value->clearForClose(); blink::Platform::current()->histogramCustomCounts("WebCore.ScriptController.clearForClose", (currentTime() - start) * 1000, 0, 10000, 50); } -void ScriptController::updateSecurityOrigin() +void ScriptController::updateSecurityOrigin(SecurityOrigin* origin) { - m_windowShell->updateSecurityOrigin(); + m_windowShell->updateSecurityOrigin(origin); } -v8::Local<v8::Value> ScriptController::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> info[]) +v8::Local<v8::Value> ScriptController::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[]) { - // Keep Frame (and therefore ScriptController) alive. - RefPtr<Frame> protect(m_frame); + // Keep LocalFrame (and therefore ScriptController) alive. + RefPtr<LocalFrame> protect(m_frame); return ScriptController::callFunction(m_frame->document(), function, receiver, argc, info, m_isolate); } -static bool resourceInfo(const v8::Handle<v8::Function> function, String& resourceName, int& lineNumber) -{ - v8::ScriptOrigin origin = function->GetScriptOrigin(); - if (origin.ResourceName().IsEmpty()) { - resourceName = "undefined"; - lineNumber = 1; - } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringResourceName, origin.ResourceName(), false); - resourceName = stringResourceName; - lineNumber = function->GetScriptLineNumber() + 1; - } - return true; -} - -v8::Local<v8::Value> ScriptController::callFunction(ExecutionContext* context, v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate* isolate) +v8::Local<v8::Value> ScriptController::callFunction(ExecutionContext* context, v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate* isolate) { + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "FunctionCall", "data", devToolsTraceEventData(context, function, isolate)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie; if (InspectorInstrumentation::timelineAgentEnabled(context)) { + int scriptId = 0; String resourceName; - int lineNumber; - if (!resourceInfo(function, resourceName, lineNumber)) - return v8::Local<v8::Value>(); - cookie = InspectorInstrumentation::willCallFunction(context, resourceName, lineNumber); + int lineNumber = 1; + GetDevToolsFunctionInfo(function, isolate, scriptId, resourceName, lineNumber); + cookie = InspectorInstrumentation::willCallFunction(context, scriptId, resourceName, lineNumber); } v8::Local<v8::Value> result = V8ScriptRunner::callFunction(function, context, receiver, argc, info, isolate); @@ -185,9 +166,10 @@ v8::Local<v8::Value> ScriptController::callFunction(ExecutionContext* context, v v8::Local<v8::Value> ScriptController::executeScriptAndReturnValue(v8::Handle<v8::Context> context, const ScriptSourceCode& source, AccessControlStatus corsStatus) { - v8::Context::Scope scope(context); - - InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, source.url().isNull() ? String() : source.url().string(), source.startLine()); + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EvaluateScript", "data", InspectorEvaluateScriptEvent::data(m_frame, source.url().string(), source.startLine())); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. + InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, source.url().string(), source.startLine()); v8::Local<v8::Value> result; { @@ -198,20 +180,16 @@ v8::Local<v8::Value> ScriptController::executeScriptAndReturnValue(v8::Handle<v8 v8::TryCatch tryCatch; tryCatch.SetVerbose(true); - v8::Handle<v8::String> code = v8String(m_isolate, source.source()); - OwnPtr<v8::ScriptData> scriptData = V8ScriptRunner::precompileScript(code, source.resource()); + v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, m_isolate, corsStatus); - // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at - // 1, whereas v8 starts at 0. - v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(code, source.url(), source.startPosition(), scriptData.get(), m_isolate, corsStatus); - - // Keep Frame (and therefore ScriptController) alive. - RefPtr<Frame> protect(m_frame); + // Keep LocalFrame (and therefore ScriptController) alive. + RefPtr<LocalFrame> protect(m_frame); result = V8ScriptRunner::runCompiledScript(script, m_frame->document(), m_isolate); ASSERT(!tryCatch.HasCaught() || result.IsEmpty()); } InspectorInstrumentation::didEvaluateScript(cookie); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); return result; } @@ -220,59 +198,47 @@ bool ScriptController::initializeMainWorld() { if (m_windowShell->isContextInitialized()) return false; - return windowShell(mainThreadNormalWorld())->isContextInitialized(); + return windowShell(DOMWrapperWorld::mainWorld())->isContextInitialized(); } -V8WindowShell* ScriptController::existingWindowShell(DOMWrapperWorld* world) +V8WindowShell* ScriptController::existingWindowShell(DOMWrapperWorld& world) { - ASSERT(world); - - if (world->isMainWorld()) + if (world.isMainWorld()) return m_windowShell->isContextInitialized() ? m_windowShell.get() : 0; - // FIXME: Remove this block. See comment with existingWindowShellWorkaroundWorld(). - if (world == existingWindowShellWorkaroundWorld()) - return m_windowShell.get(); - - IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(world->worldId()); + IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(world.worldId()); if (iter == m_isolatedWorlds.end()) return 0; return iter->value->isContextInitialized() ? iter->value.get() : 0; } -V8WindowShell* ScriptController::windowShell(DOMWrapperWorld* world) +V8WindowShell* ScriptController::windowShell(DOMWrapperWorld& world) { - ASSERT(world); - V8WindowShell* shell = 0; - if (world->isMainWorld()) + if (world.isMainWorld()) shell = m_windowShell.get(); else { - IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(world->worldId()); + IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(world.worldId()); if (iter != m_isolatedWorlds.end()) shell = iter->value.get(); else { OwnPtr<V8WindowShell> isolatedWorldShell = V8WindowShell::create(m_frame, world, m_isolate); shell = isolatedWorldShell.get(); - m_isolatedWorlds.set(world->worldId(), isolatedWorldShell.release()); - } - } - if (!shell->isContextInitialized() && shell->initializeIfNeeded()) { - if (world->isMainWorld()) { - // FIXME: Remove this if clause. See comment with existingWindowShellWorkaroundWorld(). - m_frame->loader().dispatchDidClearWindowObjectInWorld(existingWindowShellWorkaroundWorld()); - } else { - m_frame->loader().dispatchDidClearWindowObjectInWorld(world); + m_isolatedWorlds.set(world.worldId(), isolatedWorldShell.release()); } } + if (!shell->isContextInitialized() && shell->initializeIfNeeded() && world.isMainWorld()) + m_frame->loader().dispatchDidClearWindowObjectInMainWorld(); return shell; } bool ScriptController::shouldBypassMainWorldContentSecurityPolicy() { - if (DOMWrapperWorld* world = isolatedWorldForEnteredContext(m_isolate)) - return world->isolatedWorldHasContentSecurityPolicy(); - return false; + v8::Handle<v8::Context> context = m_isolate->GetCurrentContext(); + if (context.IsEmpty() || !toDOMWindow(context)) + return false; + DOMWrapperWorld& world = DOMWrapperWorld::current(m_isolate); + return world.isIsolatedWorld() ? world.isolatedWorldHasContentSecurityPolicy() : false; } TextPosition ScriptController::eventHandlerPosition() const @@ -283,57 +249,18 @@ TextPosition ScriptController::eventHandlerPosition() const return TextPosition::minimumPosition(); } -static inline v8::Local<v8::Context> contextForWorld(ScriptController& scriptController, DOMWrapperWorld* world) -{ - return scriptController.windowShell(world)->context(); -} - -v8::Local<v8::Context> ScriptController::currentWorldContext() -{ - if (!isolate()->InContext()) - return contextForWorld(*this, mainThreadNormalWorld()); - - v8::Handle<v8::Context> context = isolate()->GetEnteredContext(); - DOMWrapperWorld* isolatedWorld = DOMWrapperWorld::isolatedWorld(context); - if (!isolatedWorld) - return contextForWorld(*this, mainThreadNormalWorld()); - - Frame* frame = toFrameIfNotDetached(context); - if (m_frame == frame) - return v8::Local<v8::Context>::New(m_isolate, context); - - return contextForWorld(*this, isolatedWorld); -} - -v8::Local<v8::Context> ScriptController::mainWorldContext() -{ - return contextForWorld(*this, mainThreadNormalWorld()); -} - -v8::Local<v8::Context> ScriptController::mainWorldContext(Frame* frame) -{ - if (!frame) - return v8::Local<v8::Context>(); - - return contextForWorld(frame->script(), mainThreadNormalWorld()); -} - // Create a V8 object with an interceptor of NPObjectPropertyGetter. -void ScriptController::bindToWindowObject(Frame* frame, const String& key, NPObject* object) +void ScriptController::bindToWindowObject(LocalFrame* frame, const String& key, NPObject* object) { - v8::HandleScope handleScope(m_isolate); - - v8::Handle<v8::Context> v8Context = ScriptController::mainWorldContext(frame); - if (v8Context.IsEmpty()) + ScriptState* scriptState = ScriptState::forMainWorld(frame); + if (scriptState->contextIsEmpty()) return; - v8::Context::Scope scope(v8Context); - + ScriptState::Scope scope(scriptState); v8::Handle<v8::Object> value = createV8ObjectForNPObject(object, 0, m_isolate); // Attach to the global object. - v8::Handle<v8::Object> global = v8Context->Global(); - global->Set(v8String(m_isolate, key), value); + scriptState->context()->Global()->Set(v8String(m_isolate, key), value); } void ScriptController::enableEval() @@ -359,13 +286,13 @@ PassRefPtr<SharedPersistent<v8::Object> > ScriptController::createPluginWrapper( ASSERT(widget); if (!widget->isPluginView()) - return 0; + return nullptr; NPObject* npObject = toPluginView(widget)->scriptableObject(); if (!npObject) - return 0; + return nullptr; - // Frame Memory Management for NPObjects + // LocalFrame Memory Management for NPObjects // ------------------------------------- // NPObjects are treated differently than other objects wrapped by JS. // NPObjects can be created either by the browser (e.g. the main @@ -374,7 +301,7 @@ PassRefPtr<SharedPersistent<v8::Object> > ScriptController::createPluginWrapper( // is especially careful to ensure NPObjects terminate at frame teardown because // if a plugin leaks a reference, it could leak its objects (or the browser's objects). // - // The Frame maintains a list of plugin objects (m_pluginObjects) + // The LocalFrame maintains a list of plugin objects (m_pluginObjects) // which it can use to quickly find the wrapped embed object. // // Inside the NPRuntime, we've added a few methods for registering @@ -430,18 +357,16 @@ static NPObject* createNoScriptObject() return 0; } -static NPObject* createScriptObject(Frame* frame, v8::Isolate* isolate) +static NPObject* createScriptObject(LocalFrame* frame, v8::Isolate* isolate) { - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> v8Context = ScriptController::mainWorldContext(frame); - if (v8Context.IsEmpty()) + ScriptState* scriptState = ScriptState::forMainWorld(frame); + if (scriptState->contextIsEmpty()) return createNoScriptObject(); - v8::Context::Scope scope(v8Context); - DOMWindow* window = frame->domWindow(); - v8::Handle<v8::Value> global = toV8(window, v8::Handle<v8::Object>(), v8Context->GetIsolate()); + ScriptState::Scope scope(scriptState); + LocalDOMWindow* window = frame->domWindow(); + v8::Handle<v8::Value> global = toV8(window, scriptState->context()->Global(), scriptState->isolate()); ASSERT(global->IsObject()); - return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(global), window, isolate); } @@ -470,18 +395,17 @@ NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement if (!canExecuteScripts(NotAboutToExecuteScript)) return createNoScriptObject(); - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> v8Context = ScriptController::mainWorldContext(m_frame); - if (v8Context.IsEmpty()) + ScriptState* scriptState = ScriptState::forMainWorld(m_frame); + if (scriptState->contextIsEmpty()) return createNoScriptObject(); - v8::Context::Scope scope(v8Context); - DOMWindow* window = m_frame->domWindow(); - v8::Handle<v8::Value> v8plugin = toV8(plugin, v8::Handle<v8::Object>(), v8Context->GetIsolate()); + ScriptState::Scope scope(scriptState); + LocalDOMWindow* window = m_frame->domWindow(); + v8::Handle<v8::Value> v8plugin = toV8(plugin, scriptState->context()->Global(), scriptState->isolate()); if (!v8plugin->IsObject()) return createNoScriptObject(); - return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(v8plugin), window, v8Context->GetIsolate()); + return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(v8plugin), window, scriptState->isolate()); } void ScriptController::clearWindowShell() @@ -492,7 +416,7 @@ void ScriptController::clearWindowShell() m_windowShell->clearForNavigation(); for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin(); iter != m_isolatedWorlds.end(); ++iter) iter->value->clearForNavigation(); - V8GCController::hintForCollectGarbage(); + clearScriptObjects(); blink::Platform::current()->histogramCustomCounts("WebCore.ScriptController.clearWindowShell", (currentTime() - start) * 1000, 0, 10000, 50); } @@ -503,17 +427,14 @@ void ScriptController::setCaptureCallStackForUncaughtExceptions(bool value) void ScriptController::collectIsolatedContexts(Vector<std::pair<ScriptState*, SecurityOrigin*> >& result) { - v8::HandleScope handleScope(m_isolate); for (IsolatedWorldMap::iterator it = m_isolatedWorlds.begin(); it != m_isolatedWorlds.end(); ++it) { V8WindowShell* isolatedWorldShell = it->value.get(); - SecurityOrigin* origin = isolatedWorldShell->world()->isolatedWorldSecurityOrigin(); + SecurityOrigin* origin = isolatedWorldShell->world().isolatedWorldSecurityOrigin(); if (!origin) continue; - v8::Local<v8::Context> v8Context = isolatedWorldShell->context(); - if (v8Context.IsEmpty()) + if (!isolatedWorldShell->isContextInitialized()) continue; - ScriptState* scriptState = ScriptState::forContext(v8Context); - result.append(std::pair<ScriptState*, SecurityOrigin*>(scriptState, origin)); + result.append(std::pair<ScriptState*, SecurityOrigin*>(isolatedWorldShell->scriptState(), origin)); } } @@ -534,22 +455,22 @@ int ScriptController::contextDebugId(v8::Handle<v8::Context> context) void ScriptController::updateDocument() { - // For an uninitialized main window shell, do not incur the cost of context initialization during FrameLoader::init(). - if ((!m_windowShell->isContextInitialized() || !m_windowShell->isGlobalInitialized()) && m_frame->loader().stateMachine()->creatingInitialEmptyDocument()) + // For an uninitialized main window shell, do not incur the cost of context initialization. + if (!m_windowShell->isGlobalInitialized()) return; if (!initializeMainWorld()) - windowShell(mainThreadNormalWorld())->updateDocument(); + windowShell(DOMWrapperWorld::mainWorld())->updateDocument(); } void ScriptController::namedItemAdded(HTMLDocument* doc, const AtomicString& name) { - windowShell(mainThreadNormalWorld())->namedItemAdded(doc, name); + windowShell(DOMWrapperWorld::mainWorld())->namedItemAdded(doc, name); } void ScriptController::namedItemRemoved(HTMLDocument* doc, const AtomicString& name) { - windowShell(mainThreadNormalWorld())->namedItemRemoved(doc, name); + windowShell(DOMWrapperWorld::mainWorld())->namedItemRemoved(doc, name); } bool ScriptController::canExecuteScripts(ReasonForCallingCanExecuteScripts reason) @@ -567,7 +488,7 @@ bool ScriptController::canExecuteScripts(ReasonForCallingCanExecuteScripts reaso } Settings* settings = m_frame->settings(); - const bool allowed = m_frame->loader().client()->allowScript(settings && settings->isScriptEnabled()); + const bool allowed = m_frame->loader().client()->allowScript(settings && settings->scriptEnabled()); if (!allowed && reason == AboutToExecuteScript) m_frame->loader().client()->didNotAllowScript(); return allowed; @@ -582,30 +503,30 @@ bool ScriptController::executeScriptIfJavaScriptURL(const KURL& url) || !m_frame->document()->contentSecurityPolicy()->allowJavaScriptURLs(m_frame->document()->url(), eventHandlerPosition().m_line)) return true; - // We need to hold onto the Frame here because executing script can + // We need to hold onto the LocalFrame here because executing script can // destroy the frame. - RefPtr<Frame> protector(m_frame); - RefPtr<Document> ownerDocument(m_frame->document()); + RefPtr<LocalFrame> protector(m_frame); + RefPtrWillBeRawPtr<Document> ownerDocument(m_frame->document()); const int javascriptSchemeLength = sizeof("javascript:") - 1; bool locationChangeBefore = m_frame->navigationScheduler().locationChangePending(); String decodedURL = decodeURLEscapeSequences(url.string()); - ScriptValue result = evaluateScriptInMainWorld(ScriptSourceCode(decodedURL.substring(javascriptSchemeLength)), NotSharableCrossOrigin, DoNotExecuteScriptWhenScriptsDisabled); + v8::HandleScope handleScope(m_isolate); + v8::Local<v8::Value> result = evaluateScriptInMainWorld(ScriptSourceCode(decodedURL.substring(javascriptSchemeLength)), NotSharableCrossOrigin, DoNotExecuteScriptWhenScriptsDisabled); // If executing script caused this frame to be removed from the page, we // don't want to try to replace its document! if (!m_frame->page()) return true; - String scriptResult; - if (!result.getString(scriptResult)) + if (result.IsEmpty() || !result->IsString()) return true; + String scriptResult = toCoreString(v8::Handle<v8::String>::Cast(result)); // We're still in a frame, so there should be a DocumentLoader. ASSERT(m_frame->document()->loader()); - if (!locationChangeBefore && m_frame->navigationScheduler().locationChangePending()) return true; @@ -620,80 +541,77 @@ bool ScriptController::executeScriptIfJavaScriptURL(const KURL& url) void ScriptController::executeScriptInMainWorld(const String& script, ExecuteScriptPolicy policy) { + v8::HandleScope handleScope(m_isolate); evaluateScriptInMainWorld(ScriptSourceCode(script), NotSharableCrossOrigin, policy); } void ScriptController::executeScriptInMainWorld(const ScriptSourceCode& sourceCode, AccessControlStatus corsStatus) { + v8::HandleScope handleScope(m_isolate); evaluateScriptInMainWorld(sourceCode, corsStatus, DoNotExecuteScriptWhenScriptsDisabled); } -ScriptValue ScriptController::executeScriptInMainWorldAndReturnValue(const ScriptSourceCode& sourceCode) +v8::Local<v8::Value> ScriptController::executeScriptInMainWorldAndReturnValue(const ScriptSourceCode& sourceCode) { return evaluateScriptInMainWorld(sourceCode, NotSharableCrossOrigin, DoNotExecuteScriptWhenScriptsDisabled); } -ScriptValue ScriptController::evaluateScriptInMainWorld(const ScriptSourceCode& sourceCode, AccessControlStatus corsStatus, ExecuteScriptPolicy policy) +v8::Local<v8::Value> ScriptController::evaluateScriptInMainWorld(const ScriptSourceCode& sourceCode, AccessControlStatus corsStatus, ExecuteScriptPolicy policy) { if (policy == DoNotExecuteScriptWhenScriptsDisabled && !canExecuteScripts(AboutToExecuteScript)) - return ScriptValue(); + return v8::Local<v8::Value>(); String sourceURL = sourceCode.url(); const String* savedSourceURL = m_sourceURL; m_sourceURL = &sourceURL; - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> v8Context = ScriptController::mainWorldContext(m_frame); - if (v8Context.IsEmpty()) - return ScriptValue(); + ScriptState* scriptState = ScriptState::forMainWorld(m_frame); + if (scriptState->contextIsEmpty()) + return v8::Local<v8::Value>(); + + v8::EscapableHandleScope handleScope(scriptState->isolate()); + ScriptState::Scope scope(scriptState); - RefPtr<Frame> protect(m_frame); + RefPtr<LocalFrame> protect(m_frame); if (m_frame->loader().stateMachine()->isDisplayingInitialEmptyDocument()) m_frame->loader().didAccessInitialDocument(); OwnPtr<ScriptSourceCode> maybeProcessedSourceCode = InspectorInstrumentation::preprocess(m_frame, sourceCode); const ScriptSourceCode& sourceCodeToCompile = maybeProcessedSourceCode ? *maybeProcessedSourceCode : sourceCode; - v8::Local<v8::Value> object = executeScriptAndReturnValue(v8Context, sourceCodeToCompile, corsStatus); + v8::Local<v8::Value> object = executeScriptAndReturnValue(scriptState->context(), sourceCodeToCompile, corsStatus); m_sourceURL = savedSourceURL; if (object.IsEmpty()) - return ScriptValue(); + return v8::Local<v8::Value>(); - return ScriptValue(object, m_isolate); + return handleScope.Escape(object); } -void ScriptController::executeScriptInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup, Vector<ScriptValue>* results) +void ScriptController::executeScriptInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup, Vector<v8::Local<v8::Value> >* results) { ASSERT(worldID > 0); - v8::HandleScope handleScope(m_isolate); - v8::Local<v8::Array> v8Results; - { - v8::EscapableHandleScope evaluateHandleScope(m_isolate); - RefPtr<DOMWrapperWorld> world = DOMWrapperWorld::ensureIsolatedWorld(worldID, extensionGroup); - V8WindowShell* isolatedWorldShell = windowShell(world.get()); - - if (!isolatedWorldShell->isContextInitialized()) - return; - - v8::Local<v8::Context> context = isolatedWorldShell->context(); - v8::Context::Scope contextScope(context); - v8::Local<v8::Array> resultArray = v8::Array::New(m_isolate, sources.size()); + RefPtr<DOMWrapperWorld> world = DOMWrapperWorld::ensureIsolatedWorld(worldID, extensionGroup); + V8WindowShell* isolatedWorldShell = windowShell(*world); + if (!isolatedWorldShell->isContextInitialized()) + return; - for (size_t i = 0; i < sources.size(); ++i) { - v8::Local<v8::Value> evaluationResult = executeScriptAndReturnValue(context, sources[i]); - if (evaluationResult.IsEmpty()) - evaluationResult = v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate)); - resultArray->Set(i, evaluationResult); - } + ScriptState* scriptState = isolatedWorldShell->scriptState(); + v8::EscapableHandleScope handleScope(scriptState->isolate()); + ScriptState::Scope scope(scriptState); + v8::Local<v8::Array> resultArray = v8::Array::New(m_isolate, sources.size()); - v8Results = evaluateHandleScope.Escape(resultArray); + for (size_t i = 0; i < sources.size(); ++i) { + v8::Local<v8::Value> evaluationResult = executeScriptAndReturnValue(scriptState->context(), sources[i]); + if (evaluationResult.IsEmpty()) + evaluationResult = v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate)); + resultArray->Set(i, evaluationResult); } - if (results && !v8Results.IsEmpty()) { - for (size_t i = 0; i < v8Results->Length(); ++i) - results->append(ScriptValue(v8Results->Get(i), m_isolate)); + if (results) { + for (size_t i = 0; i < resultArray->Length(); ++i) + results->append(handleScope.Escape(resultArray->Get(i))); } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.h index 83793c7a96a..3da4d2c6662 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.h @@ -49,12 +49,12 @@ namespace WebCore { class DOMWrapperWorld; class ExecutionContext; class Event; -class Frame; class HTMLDocument; class HTMLPlugInElement; class KURL; -class ScriptSourceCode; +class LocalFrame; class ScriptState; +class ScriptSourceCode; class SecurityOrigin; class V8WindowShell; class Widget; @@ -73,17 +73,17 @@ public: DoNotExecuteScriptWhenScriptsDisabled }; - ScriptController(Frame*); + ScriptController(LocalFrame*); ~ScriptController(); bool initializeMainWorld(); - V8WindowShell* windowShell(DOMWrapperWorld*); - V8WindowShell* existingWindowShell(DOMWrapperWorld*); + V8WindowShell* windowShell(DOMWrapperWorld&); + V8WindowShell* existingWindowShell(DOMWrapperWorld&); // Evaluate JavaScript in the main world. void executeScriptInMainWorld(const String&, ExecuteScriptPolicy = DoNotExecuteScriptWhenScriptsDisabled); void executeScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus = NotSharableCrossOrigin); - ScriptValue executeScriptInMainWorldAndReturnValue(const ScriptSourceCode&); + v8::Local<v8::Value> executeScriptInMainWorldAndReturnValue(const ScriptSourceCode&); v8::Local<v8::Value> executeScriptAndReturnValue(v8::Handle<v8::Context>, const ScriptSourceCode&, AccessControlStatus = NotSharableCrossOrigin); // Executes JavaScript in an isolated world. The script gets its own global scope, @@ -94,13 +94,13 @@ public: // Otherwise, a new world is created. // // FIXME: Get rid of extensionGroup here. - void executeScriptInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup, Vector<ScriptValue>* results); + void executeScriptInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup, Vector<v8::Local<v8::Value> >* results); // Returns true if argument is a JavaScript URL. bool executeScriptIfJavaScriptURL(const KURL&); - v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> argv[]); - static v8::Local<v8::Value> callFunction(ExecutionContext*, v8::Handle<v8::Function>, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate*); + v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, v8::Handle<v8::Value>, int argc, v8::Handle<v8::Value> argv[]); + static v8::Local<v8::Value> callFunction(ExecutionContext*, v8::Handle<v8::Function>, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate*); // Returns true if the current world is isolated, and has its own Content // Security Policy. In this case, the policy of the main world should be @@ -108,42 +108,33 @@ public: bool shouldBypassMainWorldContentSecurityPolicy(); // Creates a property of the global object of a frame. - void bindToWindowObject(Frame*, const String& key, NPObject*); + void bindToWindowObject(LocalFrame*, const String& key, NPObject*); PassRefPtr<SharedPersistent<v8::Object> > createPluginWrapper(Widget*); void enableEval(); void disableEval(const String& errorMessage); - static bool canAccessFromCurrentOrigin(Frame*); + static bool canAccessFromCurrentOrigin(LocalFrame*); static void setCaptureCallStackForUncaughtExceptions(bool); void collectIsolatedContexts(Vector<std::pair<ScriptState*, SecurityOrigin*> >&); bool canExecuteScripts(ReasonForCallingCanExecuteScripts); - // Returns V8 Context. If none exists, creates a new context. - // It is potentially slow and consumes memory. - static v8::Local<v8::Context> mainWorldContext(Frame*); - v8::Local<v8::Context> mainWorldContext(); - v8::Local<v8::Context> currentWorldContext(); - TextPosition eventHandlerPosition() const; - const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script. - void clearWindowShell(); void updateDocument(); void namedItemAdded(HTMLDocument*, const AtomicString&); void namedItemRemoved(HTMLDocument*, const AtomicString&); - void updateSecurityOrigin(); + void updateSecurityOrigin(SecurityOrigin*); void clearScriptObjects(); void cleanupScriptObjectsForPlugin(Widget*); void clearForClose(); - void clearForOutOfMemory(); NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*); NPObject* windowScriptNPObject(); @@ -163,10 +154,9 @@ private: typedef HashMap<int, OwnPtr<V8WindowShell> > IsolatedWorldMap; typedef HashMap<Widget*, NPObject*> PluginObjectMap; - ScriptValue evaluateScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus, ExecuteScriptPolicy); - void clearForClose(bool destroyGlobal); + v8::Local<v8::Value> evaluateScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus, ExecuteScriptPolicy); - Frame* m_frame; + LocalFrame* m_frame; const String* m_sourceURL; v8::Isolate* m_isolate; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.cpp index 4195a44baa2..7b100c6cffb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.cpp @@ -31,16 +31,18 @@ #include "config.h" #include "bindings/v8/ScriptDebugServer.h" -#include "DebuggerScriptSource.h" -#include "V8JavaScriptCallFrame.h" +#include "bindings/core/v8/V8JavaScriptCallFrame.h" #include "bindings/v8/ScopedPersistent.h" +#include "bindings/v8/ScriptCallStackFactory.h" #include "bindings/v8/ScriptController.h" -#include "bindings/v8/ScriptObject.h" #include "bindings/v8/ScriptSourceCode.h" +#include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ScriptRunner.h" +#include "core/DebuggerScriptSource.h" #include "core/inspector/JavaScriptCallFrame.h" #include "core/inspector/ScriptDebugListener.h" +#include "platform/JSONValues.h" #include "wtf/StdLibExtras.h" #include "wtf/Vector.h" #include "wtf/dtoa/utils.h" @@ -89,16 +91,16 @@ String ScriptDebugServer::setBreakpoint(const String& sourceID, const ScriptBrea v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); - v8::Local<v8::Object> info = v8::Object::New(); + v8::Local<v8::Object> info = v8::Object::New(m_isolate); info->Set(v8AtomicString(m_isolate, "sourceID"), v8String(debuggerContext->GetIsolate(), sourceID)); - info->Set(v8AtomicString(m_isolate, "lineNumber"), v8::Integer::New(scriptBreakpoint.lineNumber, debuggerContext->GetIsolate())); - info->Set(v8AtomicString(m_isolate, "columnNumber"), v8::Integer::New(scriptBreakpoint.columnNumber, debuggerContext->GetIsolate())); + info->Set(v8AtomicString(m_isolate, "lineNumber"), v8::Integer::New(debuggerContext->GetIsolate(), scriptBreakpoint.lineNumber)); + info->Set(v8AtomicString(m_isolate, "columnNumber"), v8::Integer::New(debuggerContext->GetIsolate(), scriptBreakpoint.columnNumber)); info->Set(v8AtomicString(m_isolate, "interstatementLocation"), v8Boolean(interstatementLocation, debuggerContext->GetIsolate())); info->Set(v8AtomicString(m_isolate, "condition"), v8String(debuggerContext->GetIsolate(), scriptBreakpoint.condition)); v8::Handle<v8::Function> setBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "setBreakpoint"))); v8::Handle<v8::Value> breakpointId = v8::Debug::Call(setBreakpointFunction, info); - if (!breakpointId->IsString()) + if (breakpointId.IsEmpty() || !breakpointId->IsString()) return ""; *actualLineNumber = info->Get(v8AtomicString(m_isolate, "lineNumber"))->Int32Value(); *actualColumnNumber = info->Get(v8AtomicString(m_isolate, "columnNumber"))->Int32Value(); @@ -111,7 +113,7 @@ void ScriptDebugServer::removeBreakpoint(const String& breakpointId) v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); - v8::Local<v8::Object> info = v8::Object::New(); + v8::Local<v8::Object> info = v8::Object::New(m_isolate); info->Set(v8AtomicString(m_isolate, "breakpointId"), v8String(debuggerContext->GetIsolate(), breakpointId)); v8::Handle<v8::Function> removeBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "removeBreakpoint"))); @@ -136,7 +138,7 @@ void ScriptDebugServer::setBreakpointsActivated(bool activated) v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); - v8::Local<v8::Object> info = v8::Object::New(); + v8::Local<v8::Object> info = v8::Object::New(m_isolate); info->Set(v8AtomicString(m_isolate, "enabled"), v8::Boolean::New(m_isolate, activated)); v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "setBreakpointsActivated"))); v8::Debug::Call(setBreakpointsActivated, info); @@ -161,14 +163,13 @@ void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pauseOn v8::HandleScope scope(m_isolate); v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); - v8::Handle<v8::Value> argv[] = { v8::Int32::New(pauseOnExceptionsState, m_isolate) }; + v8::Handle<v8::Value> argv[] = { v8::Int32::New(m_isolate, pauseOnExceptionsState) }; callDebuggerMethod("setPauseOnExceptionsState", 1, argv); } void ScriptDebugServer::setPauseOnNextStatement(bool pause) { - if (isPaused()) - return; + ASSERT(!isPaused()); if (pause) v8::Debug::DebugBreak(m_isolate); else @@ -179,8 +180,7 @@ bool ScriptDebugServer::canBreakProgram() { if (!m_breakpointsActivated) return false; - v8::HandleScope scope(m_isolate); - return !m_isolate->GetCurrentContext().IsEmpty(); + return m_isolate->InContext(); } void ScriptDebugServer::breakProgram() @@ -195,65 +195,56 @@ void ScriptDebugServer::breakProgram() m_breakProgramCallbackTemplate.set(m_isolate, templ); } - m_pausedContext = m_isolate->GetCurrentContext(); v8::Handle<v8::Function> breakProgramFunction = m_breakProgramCallbackTemplate.newLocal(m_isolate)->GetFunction(); v8::Debug::Call(breakProgramFunction); - m_pausedContext.Clear(); } void ScriptDebugServer::continueProgram() { if (isPaused()) quitMessageLoopOnPause(); - m_executionState.clear(); + m_pausedScriptState.clear(); + m_executionState.Clear(); } void ScriptDebugServer::stepIntoStatement() { ASSERT(isPaused()); + ASSERT(!m_executionState.IsEmpty()); v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Value> argv[] = { m_executionState.newLocal(m_isolate) }; + v8::Handle<v8::Value> argv[] = { m_executionState }; callDebuggerMethod(stepIntoV8MethodName, 1, argv); continueProgram(); } -void ScriptDebugServer::stepCommandWithFrame(const char* functionName, const ScriptValue& frame) +void ScriptDebugServer::stepOverStatement() { ASSERT(isPaused()); + ASSERT(!m_executionState.IsEmpty()); v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Value> callFrame; - if (frame.hasNoValue()) { - callFrame = v8::Undefined(m_isolate); - } else { - JavaScriptCallFrame* impl = V8JavaScriptCallFrame::toNative(v8::Handle<v8::Object>::Cast(frame.v8Value())); - callFrame = impl->innerCallFrame(); - } - - v8::Handle<v8::Value> argv[] = { - m_executionState.newLocal(m_isolate), - callFrame - }; - - callDebuggerMethod(functionName, 2, argv); + v8::Handle<v8::Value> argv[] = { m_executionState }; + callDebuggerMethod("stepOverStatement", 1, argv); continueProgram(); } -void ScriptDebugServer::stepOverStatement(const ScriptValue& frame) +void ScriptDebugServer::stepOutOfFunction() { - stepCommandWithFrame("stepOverStatement", frame); -} - -void ScriptDebugServer::stepOutOfFunction(const ScriptValue& frame) -{ - stepCommandWithFrame(stepOutV8MethodName, frame); + ASSERT(isPaused()); + ASSERT(!m_executionState.IsEmpty()); + v8::HandleScope handleScope(m_isolate); + v8::Handle<v8::Value> argv[] = { m_executionState }; + callDebuggerMethod(stepOutV8MethodName, 1, argv); + continueProgram(); } -bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>& errorData, ScriptValue* newCallFrames, ScriptObject* result) +bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>& errorData, ScriptValue* newCallFrames, RefPtr<JSONObject>* result) { class EnableLiveEditScope { public: - EnableLiveEditScope() { v8::Debug::SetLiveEditEnabled(true); } - ~EnableLiveEditScope() { v8::Debug::SetLiveEditEnabled(false); } + explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { v8::Debug::SetLiveEditEnabled(m_isolate, true); } + ~EnableLiveEditScope() { v8::Debug::SetLiveEditEnabled(m_isolate, false); } + private: + v8::Isolate* m_isolate; }; ensureDebuggerScriptCompiled(); @@ -264,11 +255,11 @@ bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& ne if (!isPaused()) contextScope = adoptPtr(new v8::Context::Scope(debuggerContext)); - v8::Handle<v8::Value> argv[] = { v8String(debuggerContext->GetIsolate(), sourceID), v8String(debuggerContext->GetIsolate(), newContent), v8Boolean(preview, debuggerContext->GetIsolate()) }; + v8::Handle<v8::Value> argv[] = { v8String(m_isolate, sourceID), v8String(m_isolate, newContent), v8Boolean(preview, m_isolate) }; v8::Local<v8::Value> v8result; { - EnableLiveEditScope enableLiveEditScope; + EnableLiveEditScope enableLiveEditScope(m_isolate); v8::TryCatch tryCatch; tryCatch.SetVerbose(false); v8result = callDebuggerMethod("liveEditScriptSource", 3, argv); @@ -288,8 +279,9 @@ bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& ne case 0: { v8::Local<v8::Value> normalResult = resultTuple->Get(1); - if (normalResult->IsObject()) - *result = ScriptObject(ScriptState::current(), normalResult->ToObject()); + RefPtr<JSONValue> jsonResult = v8ToJSONValue(m_isolate, normalResult, JSONValue::maxDepth); + if (jsonResult) + *result = jsonResult->asObject(); // Call stack may have changed after if the edited function was on the stack. if (!preview && isPaused()) *newCallFrames = currentCallFrames(); @@ -314,40 +306,71 @@ bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& ne return false; } -PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::wrapCallFrames(v8::Handle<v8::Object> executionState, int maximumLimit) +int ScriptDebugServer::frameCount() { + ASSERT(isPaused()); + ASSERT(!m_executionState.IsEmpty()); + v8::Handle<v8::Value> argv[] = { m_executionState }; + v8::Handle<v8::Value> result = callDebuggerMethod("frameCount", WTF_ARRAY_LENGTH(argv), argv); + if (result->IsInt32()) + return result->Int32Value(); + return 0; +} + +PassRefPtrWillBeRawPtr<JavaScriptCallFrame> ScriptDebugServer::wrapCallFrames(int maximumLimit, ScopeInfoDetails scopeDetails) +{ + const int scopeBits = 2; + COMPILE_ASSERT(NoScopes < (1 << scopeBits), not_enough_bits_to_encode_ScopeInfoDetails); + + ASSERT(maximumLimit >= 0); + int data = (maximumLimit << scopeBits) | scopeDetails; v8::Handle<v8::Value> currentCallFrameV8; - if (executionState.IsEmpty()) { + if (m_executionState.IsEmpty()) { v8::Handle<v8::Function> currentCallFrameFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "currentCallFrame"))); - currentCallFrameV8 = v8::Debug::Call(currentCallFrameFunction, v8::Integer::New(maximumLimit, m_isolate)); + currentCallFrameV8 = v8::Debug::Call(currentCallFrameFunction, v8::Integer::New(m_isolate, data)); } else { - v8::Handle<v8::Value> argv[] = { executionState, v8::Integer::New(maximumLimit, m_isolate) }; - currentCallFrameV8 = callDebuggerMethod("currentCallFrame", 2, argv); + v8::Handle<v8::Value> argv[] = { m_executionState, v8::Integer::New(m_isolate, data) }; + currentCallFrameV8 = callDebuggerMethod("currentCallFrame", WTF_ARRAY_LENGTH(argv), argv); } ASSERT(!currentCallFrameV8.IsEmpty()); if (!currentCallFrameV8->IsObject()) - return PassRefPtr<JavaScriptCallFrame>(); + return nullptr; return JavaScriptCallFrame::create(v8::Debug::GetDebugContext(), v8::Handle<v8::Object>::Cast(currentCallFrameV8)); } -ScriptValue ScriptDebugServer::currentCallFrames() +ScriptValue ScriptDebugServer::currentCallFramesInner(ScopeInfoDetails scopeDetails) { - v8::HandleScope scope(m_isolate); - v8::Handle<v8::Context> pausedContext = m_pausedContext.IsEmpty() ? m_isolate->GetCurrentContext() : m_pausedContext; - if (pausedContext.IsEmpty()) + if (!m_isolate->InContext()) return ScriptValue(); + v8::HandleScope handleScope(m_isolate); - RefPtr<JavaScriptCallFrame> currentCallFrame = wrapCallFrames(m_executionState.newLocal(m_isolate), -1); + RefPtrWillBeRawPtr<JavaScriptCallFrame> currentCallFrame = wrapCallFrames(0, scopeDetails); if (!currentCallFrame) return ScriptValue(); - v8::Context::Scope contextScope(pausedContext); - return ScriptValue(toV8(currentCallFrame.release(), v8::Handle<v8::Object>(), pausedContext->GetIsolate()), pausedContext->GetIsolate()); + ScriptState* scriptState = m_pausedScriptState ? m_pausedScriptState.get() : ScriptState::current(m_isolate); + ScriptState::Scope scope(scriptState); + return ScriptValue(scriptState, toV8(currentCallFrame.release(), scriptState->context()->Global(), m_isolate)); +} + +ScriptValue ScriptDebugServer::currentCallFrames() +{ + return currentCallFramesInner(AllScopes); +} + +ScriptValue ScriptDebugServer::currentCallFramesForAsyncStack() +{ + return currentCallFramesInner(FastAsyncScopes); +} + +PassRefPtrWillBeRawPtr<JavaScriptCallFrame> ScriptDebugServer::topCallFrameNoScopes() +{ + return wrapCallFrames(1, NoScopes); } void ScriptDebugServer::interruptAndRun(PassOwnPtr<Task> task, v8::Isolate* isolate) { - v8::Debug::DebugBreakForCommand(new ClientDataImpl(task), isolate); + v8::Debug::DebugBreakForCommand(isolate, new ClientDataImpl(task)); } void ScriptDebugServer::runPendingTasks() @@ -365,18 +388,19 @@ void ScriptDebugServer::breakProgramCallback(const v8::FunctionCallbackInfo<v8:: { ASSERT(2 == info.Length()); ScriptDebugServer* thisPtr = toScriptDebugServer(info.Data()); + ScriptState* pausedScriptState = ScriptState::current(thisPtr->m_isolate); v8::Handle<v8::Value> exception; v8::Handle<v8::Array> hitBreakpoints; - thisPtr->handleProgramBreak(v8::Handle<v8::Object>::Cast(info[0]), exception, hitBreakpoints); + thisPtr->handleProgramBreak(pausedScriptState, v8::Handle<v8::Object>::Cast(info[0]), exception, hitBreakpoints); } -void ScriptDebugServer::handleProgramBreak(v8::Handle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers) +void ScriptDebugServer::handleProgramBreak(ScriptState* pausedScriptState, v8::Handle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers) { // Don't allow nested breaks. if (isPaused()) return; - ScriptDebugListener* listener = getDebugListenerForContext(m_pausedContext); + ScriptDebugListener* listener = getDebugListenerForContext(pausedScriptState->context()); if (!listener) return; @@ -390,20 +414,24 @@ void ScriptDebugServer::handleProgramBreak(v8::Handle<v8::Object> executionState } } - m_executionState.set(m_isolate, executionState); - ScriptState* currentCallFrameState = ScriptState::forContext(m_pausedContext); - listener->didPause(currentCallFrameState, currentCallFrames(), ScriptValue(exception, currentCallFrameState->isolate()), breakpointIds); - - m_runningNestedMessageLoop = true; - runMessageLoopOnPause(m_pausedContext); - m_runningNestedMessageLoop = false; -} - -void ScriptDebugServer::handleProgramBreak(const v8::Debug::EventDetails& eventDetails, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers) -{ - m_pausedContext = eventDetails.GetEventContext(); - handleProgramBreak(eventDetails.GetExecutionState(), exception, hitBreakpointNumbers); - m_pausedContext.Clear(); + m_pausedScriptState = pausedScriptState; + m_executionState = executionState; + ScriptDebugListener::SkipPauseRequest result = listener->didPause(pausedScriptState, currentCallFrames(), ScriptValue(pausedScriptState, exception), breakpointIds); + if (result == ScriptDebugListener::NoSkip) { + m_runningNestedMessageLoop = true; + runMessageLoopOnPause(pausedScriptState->context()); + m_runningNestedMessageLoop = false; + } + m_pausedScriptState.clear(); + m_executionState.Clear(); + + if (result == ScriptDebugListener::StepInto) { + v8::Handle<v8::Value> argv[] = { executionState }; + callDebuggerMethod(stepIntoV8MethodName, 1, argv); + } else if (result == ScriptDebugListener::StepOut) { + v8::Handle<v8::Value> argv[] = { executionState }; + callDebuggerMethod(stepOutV8MethodName, 1, argv); + } } void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails) @@ -412,22 +440,6 @@ void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& even thisPtr->handleV8DebugEvent(eventDetails); } -bool ScriptDebugServer::executeSkipPauseRequest(ScriptDebugListener::SkipPauseRequest request, v8::Handle<v8::Object> executionState) -{ - switch (request) { - case ScriptDebugListener::NoSkip: - return false; - case ScriptDebugListener::Continue: - return true; - case ScriptDebugListener::StepInto: - case ScriptDebugListener::StepOut: - break; - } - v8::Handle<v8::Value> argv[] = { executionState }; - callDebuggerMethod(stepIntoV8MethodName, 1, argv); - return true; -} - void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails) { v8::DebugEvent event = eventDetails.GetEvent(); @@ -463,28 +475,17 @@ void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventD // Stack trace is empty in case of syntax error. Silently continue execution in such cases. if (!stackTrace->GetFrameCount()) return; - RefPtr<JavaScriptCallFrame> topFrame = wrapCallFrames(eventDetails.GetExecutionState(), 1); - if (executeSkipPauseRequest(listener->shouldSkipExceptionPause(topFrame), eventDetails.GetExecutionState())) - return; v8::Handle<v8::Object> eventData = eventDetails.GetEventData(); v8::Handle<v8::Value> exceptionGetterValue = eventData->Get(v8AtomicString(m_isolate, "exception")); ASSERT(!exceptionGetterValue.IsEmpty() && exceptionGetterValue->IsFunction()); v8::Handle<v8::Value> exception = V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function>::Cast(exceptionGetterValue), eventData, 0, 0, m_isolate); - handleProgramBreak(eventDetails, exception, v8::Handle<v8::Array>()); + handleProgramBreak(ScriptState::from(eventContext), eventDetails.GetExecutionState(), exception, v8::Handle<v8::Array>()); } else if (event == v8::Break) { v8::Handle<v8::Function> getBreakpointNumbersFunction = v8::Local<v8::Function>::Cast(debuggerScript->Get(v8AtomicString(m_isolate, "getBreakpointNumbers"))); v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() }; v8::Handle<v8::Value> hitBreakpoints = V8ScriptRunner::callInternalFunction(getBreakpointNumbersFunction, debuggerScript, WTF_ARRAY_LENGTH(argv), argv, m_isolate); ASSERT(hitBreakpoints->IsArray()); - RefPtr<JavaScriptCallFrame> topFrame = wrapCallFrames(eventDetails.GetExecutionState(), 1); - ScriptDebugListener::SkipPauseRequest skipRequest; - if (v8::Handle<v8::Array>::Cast(hitBreakpoints)->Length()) - skipRequest = listener->shouldSkipBreakpointPause(topFrame); - else - skipRequest = listener->shouldSkipStepPause(topFrame); - if (executeSkipPauseRequest(skipRequest, eventDetails.GetExecutionState())) - return; - handleProgramBreak(eventDetails, v8::Handle<v8::Value>(), hitBreakpoints.As<v8::Array>()); + handleProgramBreak(ScriptState::from(eventContext), eventDetails.GetExecutionState(), v8::Handle<v8::Value>(), hitBreakpoints.As<v8::Array>()); } } } @@ -522,6 +523,12 @@ void ScriptDebugServer::ensureDebuggerScriptCompiled() m_debuggerScript.set(m_isolate, v8::Handle<v8::Object>::Cast(value)); } +void ScriptDebugServer::discardDebuggerScript() +{ + ASSERT(!m_debuggerScript.isEmpty()); + m_debuggerScript.clear(); +} + v8::Local<v8::Value> ScriptDebugServer::functionScopes(v8::Handle<v8::Function> function) { ensureDebuggerScriptCompiled(); @@ -547,7 +554,7 @@ v8::Handle<v8::Value> ScriptDebugServer::setFunctionVariableValue(v8::Handle<v8: v8::Handle<v8::Value> argv[] = { functionValue, - v8::Handle<v8::Value>(v8::Integer::New(scopeNumber, debuggerContext->GetIsolate())), + v8::Handle<v8::Value>(v8::Integer::New(debuggerContext->GetIsolate(), scopeNumber)), v8String(debuggerContext->GetIsolate(), variableName), newValue }; @@ -557,30 +564,32 @@ v8::Handle<v8::Value> ScriptDebugServer::setFunctionVariableValue(v8::Handle<v8: bool ScriptDebugServer::isPaused() { - return !m_executionState.isEmpty(); + return m_pausedScriptState; } -void ScriptDebugServer::compileScript(ScriptState* state, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage) +void ScriptDebugServer::compileScript(ScriptState* scriptState, const String& expression, const String& sourceURL, String* scriptId, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) { - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> context = state->context(); - if (context.IsEmpty()) + if (scriptState->contextIsEmpty()) return; - v8::Context::Scope contextScope(context); + ScriptState::Scope scope(scriptState); v8::Handle<v8::String> source = v8String(m_isolate, expression); v8::TryCatch tryCatch; v8::Local<v8::Script> script = V8ScriptRunner::compileScript(source, sourceURL, TextPosition(), 0, m_isolate); if (tryCatch.HasCaught()) { v8::Local<v8::Message> message = tryCatch.Message(); - if (!message.IsEmpty()) - *exceptionMessage = toCoreStringWithUndefinedOrNullCheck(message->Get()); + if (!message.IsEmpty()) { + *exceptionDetailsText = toCoreStringWithUndefinedOrNullCheck(message->Get()); + *lineNumber = message->GetLineNumber(); + *columnNumber = message->GetStartColumn(); + *stackTrace = createScriptCallStack(message->GetStackTrace(), message->GetStackTrace()->GetFrameCount(), m_isolate); + } return; } if (script.IsEmpty()) return; - *scriptId = String::number(script->GetId()); + *scriptId = String::number(script->GetUnboundScript()->GetId()); m_compiledScripts.set(*scriptId, adoptPtr(new ScopedPersistent<v8::Script>(m_isolate, script))); } @@ -589,7 +598,7 @@ void ScriptDebugServer::clearCompiledScripts() m_compiledScripts.clear(); } -void ScriptDebugServer::runScript(ScriptState* state, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage) +void ScriptDebugServer::runScript(ScriptState* scriptState, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) { if (!m_compiledScripts.contains(scriptId)) return; @@ -600,30 +609,33 @@ void ScriptDebugServer::runScript(ScriptState* state, const String& scriptId, Sc if (script.IsEmpty()) return; - v8::Handle<v8::Context> context = state->context(); - if (context.IsEmpty()) + if (scriptState->contextIsEmpty()) return; - v8::Context::Scope contextScope(context); + ScriptState::Scope scope(scriptState); v8::TryCatch tryCatch; - v8::Local<v8::Value> value = V8ScriptRunner::runCompiledScript(script, state->executionContext(), m_isolate); + v8::Local<v8::Value> value = V8ScriptRunner::runCompiledScript(script, scriptState->executionContext(), m_isolate); *wasThrown = false; if (tryCatch.HasCaught()) { *wasThrown = true; - *result = ScriptValue(tryCatch.Exception(), m_isolate); + *result = ScriptValue(scriptState, tryCatch.Exception()); v8::Local<v8::Message> message = tryCatch.Message(); - if (!message.IsEmpty()) - *exceptionMessage = toCoreStringWithUndefinedOrNullCheck(message->Get()); + if (!message.IsEmpty()) { + *exceptionDetailsText = toCoreStringWithUndefinedOrNullCheck(message->Get()); + *lineNumber = message->GetLineNumber(); + *columnNumber = message->GetStartColumn(); + *stackTrace = createScriptCallStack(message->GetStackTrace(), message->GetStackTrace()->GetFrameCount(), m_isolate); + } } else { - *result = ScriptValue(value, m_isolate); + *result = ScriptValue(scriptState, value); } } -PassOwnPtr<ScriptSourceCode> ScriptDebugServer::preprocess(Frame*, const ScriptSourceCode&) +PassOwnPtr<ScriptSourceCode> ScriptDebugServer::preprocess(LocalFrame*, const ScriptSourceCode&) { return PassOwnPtr<ScriptSourceCode>(); } -String ScriptDebugServer::preprocessEventListener(Frame*, const String& source, const String& url, const String& functionName) +String ScriptDebugServer::preprocessEventListener(LocalFrame*, const String& source, const String& url, const String& functionName) { return source; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.h index 3d0e07a954f..ea8d35f3dcd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.h @@ -31,25 +31,26 @@ #ifndef ScriptDebugServer_h #define ScriptDebugServer_h -#include "InspectorBackendDispatcher.h" #include "bindings/v8/ScopedPersistent.h" +#include "core/InspectorBackendDispatcher.h" #include "core/inspector/ScriptBreakpoint.h" +#include "core/inspector/ScriptCallStack.h" #include "core/inspector/ScriptDebugListener.h" -#include <v8-debug.h> #include "wtf/HashMap.h" #include "wtf/Noncopyable.h" #include "wtf/PassOwnPtr.h" #include "wtf/Vector.h" #include "wtf/text/StringHash.h" #include "wtf/text/WTFString.h" +#include <v8-debug.h> +#include <v8.h> namespace WebCore { +class ScriptState; class ScriptController; class ScriptDebugListener; -class ScriptObject; class ScriptSourceCode; -class ScriptState; class ScriptValue; class JavaScriptCallFrame; @@ -74,11 +75,14 @@ public: void breakProgram(); void continueProgram(); void stepIntoStatement(); - void stepOverStatement(const ScriptValue& frame); - void stepOutOfFunction(const ScriptValue& frame); + void stepOverStatement(); + void stepOutOfFunction(); - bool setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>&, ScriptValue* newCallFrames, ScriptObject* result); + bool setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>&, ScriptValue* newCallFrames, RefPtr<JSONObject>* result); ScriptValue currentCallFrames(); + ScriptValue currentCallFramesForAsyncStack(); + PassRefPtrWillBeRawPtr<JavaScriptCallFrame> topCallFrameNoScopes(); + int frameCount(); class Task { public: @@ -96,13 +100,16 @@ public: v8::Handle<v8::Value> setFunctionVariableValue(v8::Handle<v8::Value> functionValue, int scopeNumber, const String& variableName, v8::Handle<v8::Value> newValue); v8::Local<v8::Value> callDebuggerMethod(const char* functionName, int argc, v8::Handle<v8::Value> argv[]); - virtual void compileScript(ScriptState*, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage); + virtual void compileScript(ScriptState*, const String& expression, const String& sourceURL, String* scriptId, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace); virtual void clearCompiledScripts(); - virtual void runScript(ScriptState*, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage); + virtual void runScript(ScriptState*, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace); virtual void setPreprocessorSource(const String&) { } virtual void preprocessBeforeCompile(const v8::Debug::EventDetails&) { } - virtual PassOwnPtr<ScriptSourceCode> preprocess(Frame*, const ScriptSourceCode&); - virtual String preprocessEventListener(Frame*, const String& source, const String& url, const String& functionName); + virtual PassOwnPtr<ScriptSourceCode> preprocess(LocalFrame*, const ScriptSourceCode&); + virtual String preprocessEventListener(LocalFrame*, const String& source, const String& url, const String& functionName); + + virtual void muteWarningsAndDeprecations() { } + virtual void unmuteWarningsAndDeprecations() { } protected: explicit ScriptDebugServer(v8::Isolate*); @@ -113,8 +120,7 @@ protected: virtual void quitMessageLoopOnPause() = 0; static void breakProgramCallback(const v8::FunctionCallbackInfo<v8::Value>&); - void handleProgramBreak(v8::Handle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpoints); - void handleProgramBreak(const v8::Debug::EventDetails&, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers); + void handleProgramBreak(ScriptState* pausedScriptState, v8::Handle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpoints); static void v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails); void handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails); @@ -122,20 +128,27 @@ protected: void dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> sourceObject); void ensureDebuggerScriptCompiled(); + void discardDebuggerScript(); PauseOnExceptionsState m_pauseOnExceptionsState; ScopedPersistent<v8::Object> m_debuggerScript; - ScopedPersistent<v8::Object> m_executionState; - v8::Handle<v8::Context> m_pausedContext; + v8::Local<v8::Object> m_executionState; + RefPtr<ScriptState> m_pausedScriptState; bool m_breakpointsActivated; ScopedPersistent<v8::FunctionTemplate> m_breakProgramCallbackTemplate; HashMap<String, OwnPtr<ScopedPersistent<v8::Script> > > m_compiledScripts; v8::Isolate* m_isolate; private: - void stepCommandWithFrame(const char* functionName, const ScriptValue& frame); - PassRefPtr<JavaScriptCallFrame> wrapCallFrames(v8::Handle<v8::Object> executionState, int maximumLimit); - bool executeSkipPauseRequest(ScriptDebugListener::SkipPauseRequest, v8::Handle<v8::Object> executionState); + enum ScopeInfoDetails { + AllScopes, + FastAsyncScopes, + NoScopes // Should be the last option. + }; + + ScriptValue currentCallFramesInner(ScopeInfoDetails); + + PassRefPtrWillBeRawPtr<JavaScriptCallFrame> wrapCallFrames(int maximumLimit, ScopeInfoDetails); bool m_runningNestedMessageLoop; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.cpp index 8329708acc5..f720c88a021 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.cpp @@ -32,7 +32,6 @@ #include "bindings/v8/ScriptEventListener.h" #include "bindings/v8/ScriptController.h" -#include "bindings/v8/ScriptScope.h" #include "bindings/v8/ScriptState.h" #include "bindings/v8/V8AbstractEventListener.h" #include "bindings/v8/V8Binding.h" @@ -40,58 +39,70 @@ #include "core/dom/Document.h" #include "core/dom/DocumentParser.h" #include "core/events/EventListener.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" +#include <v8.h> namespace WebCore { -static const AtomicString& eventParameterName(bool isSVGEvent) -{ - DEFINE_STATIC_LOCAL(const AtomicString, eventString, ("event")); - DEFINE_STATIC_LOCAL(const AtomicString, evtString, ("evt")); - return isSVGEvent ? evtString : eventString; -} - -PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, const QualifiedName& name, const AtomicString& value) +PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, const QualifiedName& name, const AtomicString& value, const AtomicString& eventParameterName) { ASSERT(node); if (value.isNull()) - return 0; + return nullptr; // FIXME: Very strange: we initialize zero-based number with '1'. TextPosition position(OrdinalNumber::fromZeroBasedInt(1), OrdinalNumber::first()); String sourceURL; v8::Isolate* isolate; - if (Frame* frame = node->document().frame()) { + if (LocalFrame* frame = node->document().frame()) { isolate = toIsolate(frame); ScriptController& scriptController = frame->script(); if (!scriptController.canExecuteScripts(AboutToExecuteScript)) - return 0; + return nullptr; position = scriptController.eventHandlerPosition(); sourceURL = node->document().url().string(); } else { isolate = v8::Isolate::GetCurrent(); } - return V8LazyEventListener::create(name.localName(), eventParameterName(node->isSVGElement()), value, sourceURL, position, node, isolate); + return V8LazyEventListener::create(name.localName(), eventParameterName, value, sourceURL, position, node, isolate); } -PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, const QualifiedName& name, const AtomicString& value) +PassRefPtr<V8LazyEventListener> createAttributeEventListener(LocalFrame* frame, const QualifiedName& name, const AtomicString& value, const AtomicString& eventParameterName) { if (!frame) - return 0; + return nullptr; if (value.isNull()) - return 0; + return nullptr; ScriptController& scriptController = frame->script(); if (!scriptController.canExecuteScripts(AboutToExecuteScript)) - return 0; + return nullptr; TextPosition position = scriptController.eventHandlerPosition(); String sourceURL = frame->document()->url().string(); - return V8LazyEventListener::create(name.localName(), eventParameterName(frame->document()->isSVGDocument()), value, sourceURL, position, 0, toIsolate(frame)); + return V8LazyEventListener::create(name.localName(), eventParameterName, value, sourceURL, position, 0, toIsolate(frame)); +} + +static v8::Handle<v8::Function> eventListenerEffectiveFunction(v8::Isolate* isolate, v8::Handle<v8::Object> listenerObject) +{ + v8::Handle<v8::Function> function; + if (listenerObject->IsFunction()) { + function = v8::Handle<v8::Function>::Cast(listenerObject); + } else if (listenerObject->IsObject()) { + // Try the "handleEvent" method (EventListener interface). + v8::Handle<v8::Value> property = listenerObject->Get(v8AtomicString(isolate, "handleEvent")); + if (property.IsEmpty() || !property->IsFunction()) { + // Fall back to the "constructor" property. + property = listenerObject->Get(v8AtomicString(isolate, "constructor")); + } + if (!property.IsEmpty() && property->IsFunction()) + function = v8::Handle<v8::Function>::Cast(property); + } + return function; } String eventListenerHandlerBody(Document* document, EventListener* listener) @@ -103,11 +114,14 @@ String eventListenerHandlerBody(Document* document, EventListener* listener) V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); v8::Handle<v8::Context> context = toV8Context(document, v8Listener->world()); v8::Context::Scope contextScope(context); - v8::Handle<v8::Value> function = v8Listener->getListenerObject(document); + v8::Handle<v8::Object> object = v8Listener->getListenerObject(document); + if (object.IsEmpty()) + return ""; + v8::Handle<v8::Function> function = eventListenerEffectiveFunction(scope.GetIsolate(), object); if (function.IsEmpty()) return ""; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, functionString, function, ""); + TOSTRING_DEFAULT(V8StringResource<WithNullCheck>, functionString, function, ""); return functionString; } @@ -124,17 +138,17 @@ ScriptValue eventListenerHandler(Document* document, EventListener* listener) v8::Handle<v8::Object> function = v8Listener->getListenerObject(document); if (function.IsEmpty()) return ScriptValue(); - return ScriptValue(function, isolate); + return ScriptValue(ScriptState::from(context), function); } -ScriptState* eventListenerHandlerScriptState(Frame* frame, EventListener* listener) +ScriptState* eventListenerHandlerScriptState(LocalFrame* frame, EventListener* listener) { if (listener->type() != EventListener::JSEventListenerType) return 0; V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); v8::HandleScope scope(toIsolate(frame)); v8::Handle<v8::Context> v8Context = frame->script().windowShell(v8Listener->world())->context(); - return ScriptState::forContext(v8Context); + return ScriptState::from(v8Context); } bool eventListenerHandlerLocation(Document* document, EventListener* listener, String& sourceName, String& scriptId, int& lineNumber) @@ -146,19 +160,21 @@ bool eventListenerHandlerLocation(Document* document, EventListener* listener, S V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); v8::Handle<v8::Context> context = toV8Context(document, v8Listener->world()); v8::Context::Scope contextScope(context); - v8::Handle<v8::Object> object = v8Listener->getListenerObject(document); - if (object.IsEmpty() || !object->IsFunction()) + v8::Local<v8::Object> object = v8Listener->getListenerObject(document); + if (object.IsEmpty()) return false; - - v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(object); - int scriptIdValue = function->ScriptId(); + v8::Handle<v8::Function> function = eventListenerEffectiveFunction(scope.GetIsolate(), object); + if (function.IsEmpty()) + return false; + v8::Handle<v8::Function> originalFunction = getBoundFunction(function); + int scriptIdValue = originalFunction->ScriptId(); scriptId = String::number(scriptIdValue); - v8::ScriptOrigin origin = function->GetScriptOrigin(); + v8::ScriptOrigin origin = originalFunction->GetScriptOrigin(); if (!origin.ResourceName().IsEmpty() && origin.ResourceName()->IsString()) sourceName = toCoreString(origin.ResourceName().As<v8::String>()); else sourceName = ""; - lineNumber = function->GetScriptLineNumber(); + lineNumber = originalFunction->GetScriptLineNumber(); return true; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.h index bfb75ebaa03..097675defbd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.h @@ -33,22 +33,21 @@ #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8LazyEventListener.h" - #include "wtf/PassRefPtr.h" namespace WebCore { class Document; class EventListener; - class Frame; + class LocalFrame; class Node; class QualifiedName; - PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node*, const QualifiedName&, const AtomicString& value); - PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame*, const QualifiedName&, const AtomicString& value); + PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node*, const QualifiedName&, const AtomicString& value, const AtomicString& eventParameterName); + PassRefPtr<V8LazyEventListener> createAttributeEventListener(LocalFrame*, const QualifiedName&, const AtomicString& value, const AtomicString& eventParameterName); String eventListenerHandlerBody(Document*, EventListener*); ScriptValue eventListenerHandler(Document*, EventListener*); - ScriptState* eventListenerHandlerScriptState(Frame*, EventListener*); + ScriptState* eventListenerHandlerScriptState(LocalFrame*, EventListener*); bool eventListenerHandlerLocation(Document*, EventListener*, String& sourceName, String& scriptId, int& lineNumber); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunction.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunction.cpp new file mode 100644 index 00000000000..18315a4b6e3 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunction.cpp @@ -0,0 +1,32 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/v8/ScriptFunction.h" + +#include "bindings/v8/V8Binding.h" + +namespace WebCore { + +void ScriptFunction::callCallback(const v8::FunctionCallbackInfo<v8::Value>& args) +{ + v8::Isolate* isolate = args.GetIsolate(); + ASSERT(!args.Data().IsEmpty()); + ScriptFunction* function = ScriptFunction::Cast(args.Data()); + v8::Local<v8::Value> value = args.Length() > 0 ? args[0] : v8::Local<v8::Value>(v8::Undefined(isolate)); + + ScriptValue result = function->call(ScriptValue(ScriptState::current(isolate), value)); + + v8SetReturnValue(args, result.v8Value()); +} + +v8::Handle<v8::Function> ScriptFunction::adoptByGarbageCollector(PassOwnPtr<ScriptFunction> function) +{ + if (!function) + return v8::Handle<v8::Function>(); + v8::Isolate* isolate = function->isolate(); + return createClosure(&ScriptFunction::callCallback, function.leakPtr()->releaseToV8GarbageCollector(), isolate); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MIDIOutputCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunction.h index fa3b69afea6..acb379d0f7d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MIDIOutputCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunction.h @@ -28,25 +28,29 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "V8MIDIOutput.h" +#ifndef ScriptFunction_h +#define ScriptFunction_h -#include "V8MIDIAccess.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/ScriptValue.h" +#include "bindings/v8/V8GarbageCollected.h" +#include "wtf/RefCounted.h" +#include <v8.h> namespace WebCore { -v8::Handle<v8::Object> wrap(MIDIOutput* output, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(output); - ASSERT(!DOMDataStore::containsWrapper<V8MIDIOutput>(output, isolate)); +class ScriptFunction : public V8GarbageCollected<ScriptFunction> { +public: + virtual ~ScriptFunction() { } + static v8::Handle<v8::Function> adoptByGarbageCollector(PassOwnPtr<ScriptFunction>); - v8::Handle<v8::Object> wrapper = V8MIDIOutput::createWrapper(output, creationContext, isolate); +protected: + ScriptFunction(v8::Isolate* isolate) : V8GarbageCollected<ScriptFunction>(isolate) { } - if (output->midiAccess()) - V8HiddenPropertyName::setNamedHiddenReference(wrapper, "access", toV8(output->midiAccess(), creationContext, isolate)); - - return wrapper; -} +private: + virtual ScriptValue call(ScriptValue) = 0; + static void callCallback(const v8::FunctionCallbackInfo<v8::Value>& args); +}; } // namespace WebCore + +#endif diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.cpp index e8c618e9030..56637ded2af 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.cpp @@ -32,19 +32,17 @@ #include "bindings/v8/ScriptFunctionCall.h" #include "bindings/v8/ScriptController.h" -#include "bindings/v8/ScriptScope.h" #include "bindings/v8/ScriptState.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ObjectConstructor.h" #include "bindings/v8/V8ScriptRunner.h" -#include "bindings/v8/V8Utilities.h" #include <v8.h> namespace WebCore { -void ScriptCallArgumentHandler::appendArgument(const ScriptObject& argument) +void ScriptCallArgumentHandler::appendArgument(const ScriptValue& argument) { if (argument.scriptState() != m_scriptState) { ASSERT_NOT_REACHED(); @@ -53,67 +51,72 @@ void ScriptCallArgumentHandler::appendArgument(const ScriptObject& argument) m_arguments.append(argument); } -void ScriptCallArgumentHandler::appendArgument(const ScriptValue& argument) -{ - m_arguments.append(argument); -} - void ScriptCallArgumentHandler::appendArgument(const String& argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8String(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8String(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(const char* argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8String(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8String(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(long argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8::Number::New(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(long long argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8::Number::New(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument))); } -void ScriptCallArgumentHandler::appendArgument(unsigned int argument) +void ScriptCallArgumentHandler::appendArgument(unsigned argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8::Number::New(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(unsigned long argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8::Number::New(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(int argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8::Number::New(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(bool argument) { v8::Isolate* isolate = m_scriptState->isolate(); - m_arguments.append(ScriptValue(v8Boolean(argument, isolate), isolate)); + m_arguments.append(ScriptValue(m_scriptState.get(), v8Boolean(argument, isolate))); } -ScriptFunctionCall::ScriptFunctionCall(const ScriptObject& thisObject, const String& name) +void ScriptCallArgumentHandler::appendArgument(const Vector<ScriptValue>& argument) +{ + v8::Isolate* isolate = m_scriptState->isolate(); + ScriptState::Scope scope(m_scriptState.get()); + v8::Handle<v8::Array> result = v8::Array::New(isolate, argument.size()); + for (size_t i = 0; i < argument.size(); ++i) + result->Set(v8::Integer::New(isolate, i), argument[i].v8Value()); + m_arguments.append(ScriptValue(m_scriptState.get(), result)); +} + +ScriptFunctionCall::ScriptFunctionCall(const ScriptValue& thisObject, const String& name) : ScriptCallArgumentHandler(thisObject.scriptState()) , m_thisObject(thisObject) , m_name(name) @@ -122,11 +125,13 @@ ScriptFunctionCall::ScriptFunctionCall(const ScriptObject& thisObject, const Str ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions) { - ScriptScope scope(m_scriptState, reportExceptions); + ScriptState::Scope scope(m_scriptState.get()); + v8::TryCatch tryCatch; + tryCatch.SetVerbose(reportExceptions); - v8::Handle<v8::Object> thisObject = m_thisObject.v8Object(); + v8::Handle<v8::Object> thisObject = v8::Handle<v8::Object>::Cast(m_thisObject.v8Value()); v8::Local<v8::Value> value = thisObject->Get(v8String(m_scriptState->isolate(), m_name)); - if (!scope.success()) { + if (tryCatch.HasCaught()) { hadException = true; return ScriptValue(); } @@ -140,13 +145,13 @@ ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions) ASSERT(!info[i].IsEmpty()); } - v8::Local<v8::Value> result = V8ScriptRunner::callFunction(function, getExecutionContext(), thisObject, m_arguments.size(), info.get(), m_scriptState->isolate()); - if (!scope.success()) { + v8::Local<v8::Value> result = V8ScriptRunner::callFunction(function, m_scriptState->executionContext(), thisObject, m_arguments.size(), info.get(), m_scriptState->isolate()); + if (tryCatch.HasCaught()) { hadException = true; return ScriptValue(); } - return ScriptValue(result, m_scriptState->isolate()); + return ScriptValue(m_scriptState.get(), result); } ScriptValue ScriptFunctionCall::call() @@ -155,15 +160,17 @@ ScriptValue ScriptFunctionCall::call() return call(hadException); } -ScriptObject ScriptFunctionCall::construct(bool& hadException, bool reportExceptions) +ScriptValue ScriptFunctionCall::construct(bool& hadException, bool reportExceptions) { - ScriptScope scope(m_scriptState, reportExceptions); + ScriptState::Scope scope(m_scriptState.get()); + v8::TryCatch tryCatch; + tryCatch.SetVerbose(reportExceptions); - v8::Handle<v8::Object> thisObject = m_thisObject.v8Object(); + v8::Handle<v8::Object> thisObject = v8::Handle<v8::Object>::Cast(m_thisObject.v8Value()); v8::Local<v8::Value> value = thisObject->Get(v8String(m_scriptState->isolate(), m_name)); - if (!scope.success()) { + if (tryCatch.HasCaught()) { hadException = true; - return ScriptObject(); + return ScriptValue(); } ASSERT(value->IsFunction()); @@ -173,39 +180,13 @@ ScriptObject ScriptFunctionCall::construct(bool& hadException, bool reportExcept for (size_t i = 0; i < m_arguments.size(); ++i) info[i] = m_arguments[i].v8Value(); - v8::Local<v8::Object> result = V8ObjectConstructor::newInstance(constructor, m_arguments.size(), info.get()); - if (!scope.success()) { + v8::Local<v8::Object> result = V8ObjectConstructor::newInstance(m_scriptState->isolate(), constructor, m_arguments.size(), info.get()); + if (tryCatch.HasCaught()) { hadException = true; - return ScriptObject(); + return ScriptValue(); } - return ScriptObject(m_scriptState, result); -} - -ScriptCallback::ScriptCallback(ScriptState* state, const ScriptValue& function) - : ScriptCallArgumentHandler(state) - , m_scriptState(state) - , m_function(function) -{ -} - -ScriptValue ScriptCallback::call() -{ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); - ASSERT(m_function.v8Value()->IsFunction()); - - v8::TryCatch exceptionCatcher; - exceptionCatcher.SetVerbose(true); - v8::Handle<v8::Object> object = isolate->GetCurrentContext()->Global(); - v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(m_function.v8Value()); - - OwnPtr<v8::Handle<v8::Value>[]> info = adoptArrayPtr(new v8::Handle<v8::Value>[m_arguments.size()]); - for (size_t i = 0; i < m_arguments.size(); ++i) - info[i] = m_arguments[i].v8Value(); - - v8::Handle<v8::Value> result = ScriptController::callFunction(m_scriptState->executionContext(), function, object, m_arguments.size(), info.get(), m_scriptState->isolate()); - return ScriptValue(result, m_scriptState->isolate()); + return ScriptValue(m_scriptState.get(), result); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.h index 032b6a0b0ce..f323c3f6359 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.h @@ -31,58 +31,46 @@ #ifndef ScriptFunctionCall_h #define ScriptFunctionCall_h -#include "bindings/v8/ScriptObject.h" +#include "bindings/v8/ScriptValue.h" #include "wtf/Vector.h" #include "wtf/text/WTFString.h" namespace WebCore { class ScriptValue; - class ScriptState; class ScriptCallArgumentHandler { public: ScriptCallArgumentHandler(ScriptState* scriptState) : m_scriptState(scriptState) { } - void appendArgument(const ScriptObject&); void appendArgument(const ScriptValue&); void appendArgument(const String&); void appendArgument(const char*); void appendArgument(long); void appendArgument(long long); - void appendArgument(unsigned int); + void appendArgument(unsigned); void appendArgument(unsigned long); void appendArgument(int); void appendArgument(bool); + void appendArgument(const Vector<ScriptValue>&); protected: - ScriptState* m_scriptState; + RefPtr<ScriptState> m_scriptState; Vector<ScriptValue> m_arguments; }; class ScriptFunctionCall : public ScriptCallArgumentHandler { public: - ScriptFunctionCall(const ScriptObject& thisObject, const String& name); + ScriptFunctionCall(const ScriptValue& thisObject, const String& name); ScriptValue call(bool& hadException, bool reportExceptions = true); ScriptValue call(); - ScriptObject construct(bool& hadException, bool reportExceptions = true); + ScriptValue construct(bool& hadException, bool reportExceptions = true); protected: - ScriptObject m_thisObject; + ScriptValue m_thisObject; String m_name; }; - class ScriptCallback : public ScriptCallArgumentHandler { - public: - ScriptCallback(ScriptState*, const ScriptValue&); - - ScriptValue call(); - - private: - ScriptState* m_scriptState; - ScriptValue m_function; - }; - } // namespace WebCore #endif // ScriptFunctionCall diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.cpp index 361d8e3e965..9cc90eb4672 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.cpp @@ -41,7 +41,7 @@ namespace WebCore { static GCEventData* isolateGCEventData() { - V8PerIsolateData* isolateData = V8PerIsolateData::current(); + V8PerIsolateData* isolateData = V8PerIsolateData::from(v8::Isolate::GetCurrent()); ASSERT(isolateData); return isolateData->gcEventData(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.h index 3f95e7f46c7..ee042b5b8af 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.h @@ -31,8 +31,8 @@ #ifndef ScriptGCEvent_h #define ScriptGCEvent_h -#include "v8.h" #include "wtf/Vector.h" +#include <v8.h> namespace WebCore { @@ -80,6 +80,7 @@ private: }; +// FIXME(361045): remove ScriptGCEvent once DevTools Timeline migrates to tracing. class ScriptGCEvent { public: diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.cpp index 6077b57febd..b5c2c7f9e71 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.cpp @@ -51,25 +51,15 @@ String ScriptHeapSnapshot::title() const return toCoreString(m_snapshot->GetTitle()); } -unsigned int ScriptHeapSnapshot::uid() const -{ - return m_snapshot->GetUid(); -} - -SnapshotObjectId ScriptHeapSnapshot::maxSnapshotJSObjectId() const -{ - return m_snapshot->GetMaxSnapshotJSObjectId(); -} - namespace { -class OutputStreamAdapter : public v8::OutputStream { +class OutputStreamAdapter FINAL : public v8::OutputStream { public: OutputStreamAdapter(ScriptHeapSnapshot::OutputStream* output) : m_output(output) { } - void EndOfStream() { m_output->Close(); } - int GetChunkSize() { return 102400; } - WriteResult WriteAsciiChunk(char* data, int size) + virtual void EndOfStream() OVERRIDE { m_output->Close(); } + virtual int GetChunkSize() OVERRIDE { return 102400; } + virtual WriteResult WriteAsciiChunk(char* data, int size) OVERRIDE { m_output->Write(String(data, size)); return kContinue; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.h index 1e168599bdb..3ca4f5e9e81 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.h @@ -33,15 +33,10 @@ #include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" - -namespace v8 { -class HeapSnapshot; -} +#include <v8-profiler.h> namespace WebCore { -typedef uint32_t SnapshotObjectId; - class ScriptHeapSnapshot FINAL : public RefCounted<ScriptHeapSnapshot> { public: class OutputStream { @@ -58,9 +53,7 @@ public: ~ScriptHeapSnapshot(); String title() const; - unsigned int uid() const; void writeJSON(OutputStream* stream); - SnapshotObjectId maxSnapshotJSObjectId() const; private: ScriptHeapSnapshot(const v8::HeapSnapshot* snapshot) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptObject.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptObject.h deleted file mode 100644 index 072313d49be..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptObject.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ScriptObject_h -#define ScriptObject_h - -#include "bindings/v8/ScriptValue.h" - -#include <v8.h> - -namespace WebCore { - class InjectedScriptHost; - class InspectorFrontendHost; - class ScriptState; - - class ScriptObject : public ScriptValue { - public: - ScriptObject(ScriptState*, v8::Handle<v8::Object>); - ScriptObject(ScriptState*, const ScriptValue&); - ScriptObject() : m_scriptState(0) { }; - virtual ~ScriptObject() { } - - v8::Handle<v8::Object> v8Object() const; - ScriptState* scriptState() const { return m_scriptState; } - protected: - ScriptState* m_scriptState; - }; - - class ScriptGlobalObject { - public: - static bool set(ScriptState*, const char* name, InspectorFrontendHost*); - static bool get(ScriptState*, const char* name, ScriptObject&); - private: - ScriptGlobalObject() { } - }; - -} - -#endif // ScriptObject_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.cpp index c9674b96c7a..3c38767e8ff 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.cpp @@ -34,39 +34,41 @@ #include "bindings/v8/ScriptController.h" #include "bindings/v8/ScriptSourceCode.h" #include "bindings/v8/ScriptValue.h" +#include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ScriptRunner.h" -#include "core/page/PageConsole.h" +#include "core/frame/FrameConsole.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" #include "wtf/TemporaryChange.h" namespace WebCore { -ScriptPreprocessor::ScriptPreprocessor(const ScriptSourceCode& preprocessorSourceCode, ScriptController& controller, PageConsole& console) +ScriptPreprocessor::ScriptPreprocessor(const ScriptSourceCode& preprocessorSourceCode, LocalFrame* frame) : m_isPreprocessing(false) { + RefPtr<DOMWrapperWorld> world = DOMWrapperWorld::ensureIsolatedWorld(ScriptPreprocessorIsolatedWorldId, DOMWrapperWorld::mainWorldExtensionGroup); + m_scriptState = ScriptState::from(toV8Context(frame, *world)); + + v8::HandleScope handleScope(m_scriptState->isolate()); + ASSERT(frame); v8::TryCatch tryCatch; tryCatch.SetVerbose(true); Vector<ScriptSourceCode> sources; sources.append(preprocessorSourceCode); - Vector<ScriptValue> scriptResults; - controller.executeScriptInIsolatedWorld(ScriptPreprocessorIsolatedWorldId, sources, DOMWrapperWorld::mainWorldExtensionGroup, &scriptResults); + Vector<v8::Local<v8::Value> > scriptResults; + frame->script().executeScriptInIsolatedWorld(ScriptPreprocessorIsolatedWorldId, sources, DOMWrapperWorld::mainWorldExtensionGroup, &scriptResults); if (scriptResults.size() != 1) { - console.addMessage(JSMessageSource, ErrorMessageLevel, "ScriptPreprocessor internal error, one ScriptSourceCode must give exactly one result."); + frame->console().addMessage(JSMessageSource, ErrorMessageLevel, "ScriptPreprocessor internal error, one ScriptSourceCode must give exactly one result."); return; } - ScriptValue preprocessorFunction = scriptResults[0]; - if (!preprocessorFunction.isFunction()) { - console.addMessage(JSMessageSource, ErrorMessageLevel, "The preprocessor must compile to a function."); + v8::Local<v8::Value> preprocessorFunction = scriptResults[0]; + if (preprocessorFunction.IsEmpty() || !preprocessorFunction->IsFunction()) { + frame->console().addMessage(JSMessageSource, ErrorMessageLevel, "The preprocessor must compile to a function."); return; } - - m_world = DOMWrapperWorld::ensureIsolatedWorld(ScriptPreprocessorIsolatedWorldId, DOMWrapperWorld::mainWorldExtensionGroup); - v8::Local<v8::Context> context = m_world->context(controller); - m_isolate = context->GetIsolate(); - - m_context.set(m_isolate, context); - m_preprocessorFunction.set(m_isolate, v8::Handle<v8::Function>::Cast(preprocessorFunction.v8Value())); + m_preprocessorFunction.set(m_scriptState->isolate(), v8::Handle<v8::Function>::Cast(preprocessorFunction)); } String ScriptPreprocessor::preprocessSourceCode(const String& sourceCode, const String& sourceName) @@ -74,7 +76,7 @@ String ScriptPreprocessor::preprocessSourceCode(const String& sourceCode, const if (!isValid()) return sourceCode; - return preprocessSourceCode(sourceCode, sourceName, v8::Undefined(m_isolate)); + return preprocessSourceCode(sourceCode, sourceName, v8::Undefined(m_scriptState->isolate())); } String ScriptPreprocessor::preprocessSourceCode(const String& sourceCode, const String& sourceName, const String& functionName) @@ -82,7 +84,7 @@ String ScriptPreprocessor::preprocessSourceCode(const String& sourceCode, const if (!isValid()) return sourceCode; - v8::Handle<v8::String> functionNameString = v8String(m_isolate, functionName); + v8::Handle<v8::String> functionNameString = v8String(m_scriptState->isolate(), functionName); return preprocessSourceCode(sourceCode, sourceName, functionNameString); } @@ -91,17 +93,17 @@ String ScriptPreprocessor::preprocessSourceCode(const String& sourceCode, const if (!isValid()) return sourceCode; - v8::HandleScope handleScope(m_isolate); - v8::Context::Scope contextScope(m_context.newLocal(m_isolate)); + v8::Isolate* isolate = m_scriptState->isolate(); + ScriptState::Scope scope(m_scriptState.get()); - v8::Handle<v8::String> sourceCodeString = v8String(m_isolate, sourceCode); - v8::Handle<v8::String> sourceNameString = v8String(m_isolate, sourceName); + v8::Handle<v8::String> sourceCodeString = v8String(isolate, sourceCode); + v8::Handle<v8::String> sourceNameString = v8String(isolate, sourceName); v8::Handle<v8::Value> argv[] = { sourceCodeString, sourceNameString, functionName}; v8::TryCatch tryCatch; tryCatch.SetVerbose(true); TemporaryChange<bool> isPreprocessing(m_isPreprocessing, true); - v8::Handle<v8::Value> resultValue = V8ScriptRunner::callAsFunction(m_preprocessorFunction.newLocal(m_isolate), m_context.newLocal(m_isolate)->Global(), WTF_ARRAY_LENGTH(argv), argv); + v8::Handle<v8::Value> resultValue = V8ScriptRunner::callAsFunction(isolate, m_preprocessorFunction.newLocal(isolate), m_scriptState->context()->Global(), WTF_ARRAY_LENGTH(argv), argv); if (!resultValue.IsEmpty() && resultValue->IsString()) return toCoreStringWithNullCheck(resultValue.As<v8::String>()); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.h index 823c8be95ef..20e8ac09cb9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.h @@ -40,12 +40,11 @@ namespace WebCore { class ScriptController; class ScriptSourceCode; class ScriptDebugServer; -class PageConsole; class ScriptPreprocessor { WTF_MAKE_NONCOPYABLE(ScriptPreprocessor); public: - ScriptPreprocessor(const ScriptSourceCode&, ScriptController&, PageConsole&); + ScriptPreprocessor(const ScriptSourceCode&, LocalFrame*); String preprocessSourceCode(const String& sourceCode, const String& sourceName); String preprocessSourceCode(const String& sourceCode, const String& sourceName, const String& functionName); bool isPreprocessing() { return m_isPreprocessing; } @@ -53,9 +52,7 @@ public: private: String preprocessSourceCode(const String& sourceCode, const String& sourceName, v8::Handle<v8::Value> functionName); - RefPtr<DOMWrapperWorld> m_world; - ScopedPersistent<v8::Context> m_context; - v8::Isolate* m_isolate; + RefPtr<ScriptState> m_scriptState; ScopedPersistent<v8::Function> m_preprocessorFunction; bool m_isPreprocessing; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.cpp index 914a943a206..07a65f74a49 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.cpp @@ -31,12 +31,11 @@ #include "config.h" #include "bindings/v8/ScriptProfiler.h" -#include "V8Node.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/RetainedDOMInfo.h" -#include "bindings/v8/ScriptObject.h" +#include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8DOMWrapper.h" #include "bindings/v8/WrapperTypeInfo.h" #include "core/dom/Document.h" #include "core/inspector/BindingVisitors.h" @@ -70,19 +69,19 @@ void ScriptProfiler::start(const String& title) if (!profiler) return; v8::HandleScope handleScope(isolate); - profiler->StartCpuProfiling(v8String(isolate, title), true); + profiler->StartProfiling(v8String(isolate, title), true); } -PassRefPtr<ScriptProfile> ScriptProfiler::stop(const String& title) +PassRefPtrWillBeRawPtr<ScriptProfile> ScriptProfiler::stop(const String& title) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::CpuProfiler* profiler = isolate->GetCpuProfiler(); if (!profiler) - return 0; + return nullptr; v8::HandleScope handleScope(isolate); - const v8::CpuProfile* profile = profiler->StopCpuProfiling(v8String(isolate, title)); + v8::CpuProfile* profile = profiler->StopProfiling(v8String(isolate, title)); if (!profile) - return 0; + return nullptr; String profileTitle = toCoreString(profile->GetTitle()); double idleTime = 0.0; @@ -101,28 +100,14 @@ void ScriptProfiler::collectGarbage() v8::V8::LowMemoryNotification(); } -ScriptObject ScriptProfiler::objectByHeapObjectId(unsigned id) +ScriptValue ScriptProfiler::objectByHeapObjectId(unsigned id) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HeapProfiler* profiler = isolate->GetHeapProfiler(); - if (!profiler) - return ScriptObject(); - // As ids are unique, it doesn't matter which HeapSnapshot owns HeapGraphNode. - // We need to find first HeapSnapshot containing a node with the specified id. - const v8::HeapGraphNode* node = 0; - for (int i = 0, l = profiler->GetSnapshotCount(); i < l; ++i) { - const v8::HeapSnapshot* snapshot = profiler->GetHeapSnapshot(i); - node = snapshot->GetNodeById(id); - if (node) - break; - } - if (!node) - return ScriptObject(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Value> value = node->GetHeapValue(); - if (!value->IsObject()) - return ScriptObject(); + v8::Handle<v8::Value> value = profiler->FindObjectById(id); + if (value.IsEmpty() || !value->IsObject()) + return ScriptValue(); v8::Handle<v8::Object> object = value.As<v8::Object>(); @@ -131,11 +116,11 @@ ScriptObject ScriptProfiler::objectByHeapObjectId(unsigned id) // Skip wrapper boilerplates which are like regular wrappers but don't have // native object. if (!wrapper.IsEmpty() && wrapper->IsUndefined()) - return ScriptObject(); + return ScriptValue(); } - ScriptState* scriptState = ScriptState::forContext(object->CreationContext()); - return ScriptObject(scriptState, object); + ScriptState* scriptState = ScriptState::from(object->CreationContext()); + return ScriptValue(scriptState, object); } unsigned ScriptProfiler::getHeapObjectId(const ScriptValue& value) @@ -146,13 +131,20 @@ unsigned ScriptProfiler::getHeapObjectId(const ScriptValue& value) return id; } +void ScriptProfiler::clearHeapObjectIds() +{ + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HeapProfiler* profiler = isolate->GetHeapProfiler(); + profiler->ClearObjectIds(); +} + namespace { -class ActivityControlAdapter : public v8::ActivityControl { +class ActivityControlAdapter FINAL : public v8::ActivityControl { public: ActivityControlAdapter(ScriptProfiler::HeapSnapshotProgress* progress) : m_progress(progress), m_firstReport(true) { } - ControlOption ReportProgressValue(int done, int total) + virtual ControlOption ReportProgressValue(int done, int total) OVERRIDE { ControlOption result = m_progress->isCanceled() ? kAbort : kContinue; if (m_firstReport) { @@ -169,19 +161,16 @@ private: bool m_firstReport; }; -class GlobalObjectNameResolver : public v8::HeapProfiler::ObjectNameResolver { +class GlobalObjectNameResolver FINAL : public v8::HeapProfiler::ObjectNameResolver { public: - virtual const char* GetName(v8::Handle<v8::Object> object) + virtual const char* GetName(v8::Handle<v8::Object> object) OVERRIDE { - if (V8DOMWrapper::isWrapperOfType(object, &V8Window::wrapperTypeInfo)) { - DOMWindow* window = V8Window::toNative(object); - if (window) { - CString url = window->document()->url().string().utf8(); - m_strings.append(url); - return url.data(); - } - } - return 0; + LocalDOMWindow* window = toDOMWindow(object, v8::Isolate::GetCurrent()); + if (!window) + return 0; + CString url = window->document()->url().string().utf8(); + m_strings.append(url); + return url.data(); } private: @@ -190,9 +179,9 @@ private: } // namespace -void ScriptProfiler::startTrackingHeapObjects() +void ScriptProfiler::startTrackingHeapObjects(bool trackAllocations) { - v8::Isolate::GetCurrent()->GetHeapProfiler()->StartTrackingHeapObjects(); + v8::Isolate::GetCurrent()->GetHeapProfiler()->StartTrackingHeapObjects(trackAllocations); } namespace { @@ -244,13 +233,13 @@ PassRefPtr<ScriptHeapSnapshot> ScriptProfiler::takeHeapSnapshot(const String& ti v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HeapProfiler* profiler = isolate->GetHeapProfiler(); if (!profiler) - return 0; + return nullptr; v8::HandleScope handleScope(isolate); ASSERT(control); ActivityControlAdapter adapter(control); GlobalObjectNameResolver resolver; const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(v8String(isolate, title), &adapter, &resolver); - return snapshot ? ScriptHeapSnapshot::create(snapshot) : 0; + return snapshot ? ScriptHeapSnapshot::create(snapshot) : nullptr; } static v8::RetainedObjectInfo* retainedDOMInfo(uint16_t classId, v8::Handle<v8::Value> wrapper) @@ -292,7 +281,7 @@ void ScriptProfiler::visitNodeWrappers(WrappedNodeVisitor* visitor) // Casting to Handle is safe here, since the Persistent cannot get // GCd during visiting. v8::Handle<v8::Object>* wrapper = reinterpret_cast<v8::Handle<v8::Object>*>(value); - ASSERT_UNUSED(m_isolate, V8Node::hasInstanceInAnyWorld(*wrapper, m_isolate)); + ASSERT_UNUSED(m_isolate, V8Node::hasInstance(*wrapper, m_isolate)); ASSERT((*wrapper)->IsObject()); m_visitor->visitNode(V8Node::toNative(*wrapper)); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.h index f406c520764..167da66bf81 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.h @@ -32,7 +32,6 @@ #define ScriptProfiler_h #include "bindings/v8/ScriptHeapSnapshot.h" -#include "bindings/v8/ScriptState.h" #include "core/inspector/ScriptProfile.h" #include "wtf/Forward.h" @@ -41,11 +40,9 @@ namespace WebCore { -class ExternalArrayVisitor; class ExternalStringVisitor; class WrappedNodeVisitor; class Page; -class ScriptObject; class ScriptValue; class WorkerGlobalScope; @@ -68,13 +65,14 @@ public: }; static void collectGarbage(); - static ScriptObject objectByHeapObjectId(unsigned id); + static ScriptValue objectByHeapObjectId(unsigned id); static unsigned getHeapObjectId(const ScriptValue&); + static void clearHeapObjectIds(); static void setSamplingInterval(int intervalUs); static void start(const String& title); - static PassRefPtr<ScriptProfile> stop(const String& title); + static PassRefPtrWillBeRawPtr<ScriptProfile> stop(const String& title); static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String& title, HeapSnapshotProgress*); - static void startTrackingHeapObjects(); + static void startTrackingHeapObjects(bool trackAllocations); static void stopTrackingHeapObjects(); static unsigned requestHeapStatsUpdate(OutputStream*); static void initialize(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.cpp index bdf4105edde..d6d8b317e0b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.cpp @@ -31,31 +31,105 @@ #include "config.h" #include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolver.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8DOMWrapper.h" -#include "bindings/v8/custom/V8PromiseCustom.h" +#include "core/dom/DOMException.h" #include <v8.h> namespace WebCore { -ScriptPromise ScriptPromise::createPending(ExecutionContext* context) +namespace { + +struct WithScriptState { + // Used by ToV8Value<WithScriptState, ScriptState*>. + static v8::Handle<v8::Object> getCreationContext(ScriptState* scriptState) + { + return scriptState->context()->Global(); + } +}; + +} // namespace + +ScriptPromise::ScriptPromise(ScriptState* scriptState, v8::Handle<v8::Value> value) + : m_scriptState(scriptState) +{ + if (value.IsEmpty()) + return; + + if (!value->IsPromise()) { + m_promise = ScriptValue(scriptState, v8::Handle<v8::Value>()); + V8ThrowException::throwTypeError("the given value is not a Promise", scriptState->isolate()); + return; + } + m_promise = ScriptValue(scriptState, value); +} + +ScriptPromise ScriptPromise::then(PassOwnPtr<ScriptFunction> onFulfilled, PassOwnPtr<ScriptFunction> onRejected) +{ + if (m_promise.isEmpty()) + return ScriptPromise(); + + v8::Local<v8::Object> promise = m_promise.v8Value().As<v8::Object>(); + v8::Local<v8::Function> v8OnFulfilled = ScriptFunction::adoptByGarbageCollector(onFulfilled); + v8::Local<v8::Function> v8OnRejected = ScriptFunction::adoptByGarbageCollector(onRejected); + + ASSERT(promise->IsPromise()); + // Return this Promise if no handlers are given. + // In fact it is not the exact bahavior of Promise.prototype.then + // but that is not a problem in this case. + v8::Local<v8::Promise> resultPromise = promise.As<v8::Promise>(); + if (!v8OnFulfilled.IsEmpty()) { + resultPromise = resultPromise->Then(v8OnFulfilled); + if (resultPromise.IsEmpty()) { + // v8::Promise::Then may return an empty value, for example when + // the stack is exhausted. + return ScriptPromise(); + } + } + if (!v8OnRejected.IsEmpty()) + resultPromise = resultPromise->Catch(v8OnRejected); + + return ScriptPromise(m_scriptState.get(), resultPromise); +} + +ScriptPromise ScriptPromise::cast(ScriptState* scriptState, const ScriptValue& value) +{ + return ScriptPromise::cast(scriptState, value.v8Value()); +} + +ScriptPromise ScriptPromise::cast(ScriptState* scriptState, v8::Handle<v8::Value> value) +{ + if (value.IsEmpty()) + return ScriptPromise(); + if (value->IsPromise()) { + return ScriptPromise(scriptState, value); + } + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + resolver->resolve(value); + return promise; +} + +ScriptPromise ScriptPromise::reject(ScriptState* scriptState, const ScriptValue& value) +{ + return ScriptPromise::reject(scriptState, value.v8Value()); +} + +ScriptPromise ScriptPromise::reject(ScriptState* scriptState, v8::Handle<v8::Value> value) { - ASSERT(context); - v8::Isolate* isolate = toIsolate(context); - ASSERT(isolate->InContext()); - v8::Handle<v8::Context> v8Context = toV8Context(context, DOMWrapperWorld::current()); - v8::Handle<v8::Object> creationContext = v8Context.IsEmpty() ? v8::Object::New() : v8Context->Global(); - v8::Handle<v8::Object> promise = V8PromiseCustom::createPromise(creationContext, isolate); - return ScriptPromise(promise, isolate); + if (value.IsEmpty()) + return ScriptPromise(); + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + resolver->reject(value); + return promise; } -ScriptPromise ScriptPromise::createPending() +ScriptPromise ScriptPromise::rejectWithDOMException(ScriptState* scriptState, PassRefPtrWillBeRawPtr<DOMException> exception) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); - v8::Handle<v8::Object> promise = V8PromiseCustom::createPromise(v8::Object::New(), isolate); - return ScriptPromise(promise, isolate); + ASSERT(scriptState->isolate()->InContext()); + return reject(scriptState, ToV8Value<WithScriptState, v8::Handle<v8::Object> >::toV8Value(exception, scriptState->context()->Global(), scriptState->isolate())); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.h index 0a93b10f3b4..eb79e4e3b17 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.h @@ -31,14 +31,16 @@ #ifndef ScriptPromise_h #define ScriptPromise_h -#include "bindings/v8/ScopedPersistent.h" +#include "bindings/v8/ScriptFunction.h" #include "bindings/v8/ScriptValue.h" -#include "bindings/v8/V8ScriptRunner.h" +#include "platform/heap/Handle.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/PassRefPtr.h" #include <v8.h> namespace WebCore { -class ExecutionContext; +class DOMException; // ScriptPromise is the class for representing Promise values in C++ world. // ScriptPromise holds a Promise. @@ -48,22 +50,13 @@ class ExecutionContext; class ScriptPromise { public: // Constructs an empty promise. - ScriptPromise() - : m_promise() - { - } + ScriptPromise() { } - explicit ScriptPromise(const ScriptValue& promise) - : m_promise(promise) - { - ASSERT(!m_promise.hasNoValue()); - } + // Constructs a ScriptPromise from |promise|. + // If |promise| is not a Promise object, throws a v8 TypeError. + ScriptPromise(ScriptState*, v8::Handle<v8::Value> promise); - ScriptPromise(v8::Handle<v8::Value> promise, v8::Isolate* isolate) - : m_promise(promise, isolate) - { - ASSERT(!m_promise.hasNoValue()); - } + ScriptPromise then(PassOwnPtr<ScriptFunction> onFulfilled, PassOwnPtr<ScriptFunction> onRejected = PassOwnPtr<ScriptFunction>()); bool isObject() const { @@ -90,9 +83,9 @@ public: return m_promise.isolate(); } - bool hasNoValue() const + bool isEmpty() const { - return m_promise.hasNoValue(); + return m_promise.isEmpty(); } void clear() @@ -100,10 +93,20 @@ public: m_promise.clear(); } - static ScriptPromise createPending(); - static ScriptPromise createPending(ExecutionContext*); + // Constructs and returns a ScriptPromise from |value|. + // if |value| is not a Promise object, returns a Promise object + // resolved with |value|. + // Returns |value| itself if it is a Promise. + static ScriptPromise cast(ScriptState*, const ScriptValue& /*value*/); + static ScriptPromise cast(ScriptState*, v8::Handle<v8::Value> /*value*/); + + static ScriptPromise reject(ScriptState*, const ScriptValue&); + static ScriptPromise reject(ScriptState*, v8::Handle<v8::Value>); + + static ScriptPromise rejectWithDOMException(ScriptState*, PassRefPtrWillBeRawPtr<DOMException>); private: + RefPtr<ScriptState> m_scriptState; ScriptValue m_promise; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.cpp index fec672fcc15..ea7a6476b3f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.cpp @@ -31,20 +31,21 @@ #include "config.h" #include "bindings/v8/ScriptPromiseResolver.h" -#include "bindings/v8/ScriptState.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" -#include "bindings/v8/custom/V8PromiseCustom.h" #include <v8.h> namespace WebCore { -ScriptPromiseResolver::ScriptPromiseResolver(ScriptPromise promise) - : m_isolate(promise.isolate()) - , m_promise(promise) +ScriptPromiseResolver::ScriptPromiseResolver(ScriptState* scriptState) + : m_scriptState(scriptState) { + v8::Isolate* isolate = m_scriptState->isolate(); + ASSERT(!m_scriptState->contextIsEmpty()); + ASSERT(isolate->InContext()); + m_resolver = ScriptValue(scriptState, v8::Promise::Resolver::New(isolate)); } ScriptPromiseResolver::~ScriptPromiseResolver() @@ -52,61 +53,42 @@ ScriptPromiseResolver::~ScriptPromiseResolver() // We don't call "reject" here because it requires a caller // to be in a v8 context. - m_promise.clear(); + m_resolver.clear(); } -PassRefPtr<ScriptPromiseResolver> ScriptPromiseResolver::create(ScriptPromise promise, ExecutionContext* context) +ScriptPromise ScriptPromiseResolver::promise() { - ASSERT(promise.isolate()->InContext()); - ASSERT(context); - return adoptRef(new ScriptPromiseResolver(promise)); + ASSERT(!m_scriptState->contextIsEmpty()); + ASSERT(m_scriptState->isolate()->InContext()); + if (!m_resolver.isEmpty()) { + v8::Local<v8::Promise::Resolver> v8Resolver = m_resolver.v8Value().As<v8::Promise::Resolver>(); + return ScriptPromise(m_scriptState.get(), v8Resolver->GetPromise()); + } + return ScriptPromise(); } -PassRefPtr<ScriptPromiseResolver> ScriptPromiseResolver::create(ScriptPromise promise) +PassRefPtr<ScriptPromiseResolver> ScriptPromiseResolver::create(ScriptState* scriptState) { - ASSERT(promise.isolate()->InContext()); - return adoptRef(new ScriptPromiseResolver(promise)); -} - -bool ScriptPromiseResolver::isPending() const -{ - ASSERT(m_isolate->InContext()); - if (m_promise.hasNoValue()) - return false; - v8::Local<v8::Object> promise = m_promise.v8Value().As<v8::Object>(); - v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise); - V8PromiseCustom::PromiseState state = V8PromiseCustom::getState(internal); - return state == V8PromiseCustom::Pending; + ASSERT(scriptState->isolate()->InContext()); + return adoptRef(new ScriptPromiseResolver(scriptState)); } void ScriptPromiseResolver::resolve(v8::Handle<v8::Value> value) { - ASSERT(m_isolate->InContext()); - if (!isPending()) - return; - V8PromiseCustom::resolve(m_promise.v8Value().As<v8::Object>(), value, m_isolate); - m_promise.clear(); + ASSERT(m_scriptState->isolate()->InContext()); + if (!m_resolver.isEmpty()) { + m_resolver.v8Value().As<v8::Promise::Resolver>()->Resolve(value); + } + m_resolver.clear(); } void ScriptPromiseResolver::reject(v8::Handle<v8::Value> value) { - ASSERT(m_isolate->InContext()); - if (!isPending()) - return; - V8PromiseCustom::reject(m_promise.v8Value().As<v8::Object>(), value, m_isolate); - m_promise.clear(); -} - -void ScriptPromiseResolver::resolve(ScriptValue value) -{ - ASSERT(m_isolate->InContext()); - resolve(value.v8Value()); -} - -void ScriptPromiseResolver::reject(ScriptValue value) -{ - ASSERT(m_isolate->InContext()); - reject(value.v8Value()); + ASSERT(m_scriptState->isolate()->InContext()); + if (!m_resolver.isEmpty()) { + m_resolver.v8Value().As<v8::Promise::Resolver>()->Reject(value); + } + m_resolver.clear(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.h index 0379b244be5..513abab924b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.h @@ -31,9 +31,6 @@ #ifndef ScriptPromiseResolver_h #define ScriptPromiseResolver_h -#include "bindings/v8/DOMWrapperWorld.h" -#include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/ScriptObject.h" #include "bindings/v8/ScriptPromise.h" #include "bindings/v8/ScriptState.h" #include "bindings/v8/ScriptValue.h" @@ -50,25 +47,28 @@ class ExecutionContext; // (resolve / reject) from C++ world. // ScriptPromiseResolver holds a PromiseResolver. // Here is a typical usage: -// 1. Create a ScriptPromiseResolver from a ScriptPromise. -// 2. Pass the promise object of the holder to a JavaScript program +// 1. Create a ScriptPromiseResolver. +// 2. Pass the associated promise object to a JavaScript program // (such as XMLHttpRequest return value). // 3. Call resolve or reject when the operation completes or // the operation fails respectively. // // Most methods including constructors must be called within a v8 context. // To use ScriptPromiseResolver out of a v8 context the caller must -// enter a v8 context, for example by using ScriptScope and ScriptState. +// enter a v8 context. Please use ScriptPromiseResolverWithContext +// in such cases. // // To prevent memory leaks, you should release the reference manually // by calling resolve or reject. // Destroying the object will also release the reference. -// +// Note that ScriptPromiseResolver::promise returns an empty value when the +// resolver is already resolved or rejected. If you want to resolve a resolver +// immediately and return the associated promise, you should get the promise +// before resolving. class ScriptPromiseResolver : public RefCounted<ScriptPromiseResolver> { WTF_MAKE_NONCOPYABLE(ScriptPromiseResolver); public: - static PassRefPtr<ScriptPromiseResolver> create(ScriptPromise, ExecutionContext*); - static PassRefPtr<ScriptPromiseResolver> create(ScriptPromise); + static PassRefPtr<ScriptPromiseResolver> create(ScriptState*); // A ScriptPromiseResolver should be resolved / rejected before // its destruction. @@ -76,90 +76,75 @@ public: // entering a v8 context. ~ScriptPromiseResolver(); - // Return true if the promise object is in pending state. - bool isPending() const; + // Returns the underlying Promise. + // Note that the underlying Promise is cleared when |resolve| or |reject| + // is called. + ScriptPromise promise(); - ScriptPromise promise() + template<typename T> + void resolve(const T& value, ExecutionContext* executionContext) { - ASSERT(m_promise.isolate()->InContext()); - return m_promise; + ASSERT(m_scriptState->isolate()->InContext()); + // You should use ScriptPromiseResolverWithContext when you want + // to resolve a Promise in a non-original V8 context. + return resolve(value); } - - // To use following template methods, T must be a DOM class. - - // This method will be implemented by the code generator. - template<typename T> - void resolve(T* value, v8::Handle<v8::Object> creationContext) { resolve(toV8NoInline(value, creationContext, m_isolate)); } template<typename T> - void reject(T* value, v8::Handle<v8::Object> creationContext) { reject(toV8NoInline(value, creationContext, m_isolate)); } - + void reject(const T& value, ExecutionContext* executionContext) + { + ASSERT(m_scriptState->isolate()->InContext()); + // You should use ScriptPromiseResolverWithContext when you want + // to reject a Promise in a non-original V8 context. + return reject(value); + } template<typename T> - void resolve(PassRefPtr<T> value, v8::Handle<v8::Object> creationContext) { resolve(value.get(), creationContext); } + void resolve(const T& value) + { + ASSERT(m_scriptState->isolate()->InContext()); + resolve(toV8Value(value)); + } template<typename T> - void reject(PassRefPtr<T> value, v8::Handle<v8::Object> creationContext) { reject(value.get(), creationContext); } + void reject(const T& value) + { + ASSERT(m_scriptState->isolate()->InContext()); + reject(toV8Value(value)); + } + template<typename T> void resolve(const T& value, v8::Handle<v8::Object> creationContext) + { + ASSERT(m_scriptState->isolate()->InContext()); + resolve(toV8Value(value, creationContext)); + } + template<typename T> void reject(const T& value, v8::Handle<v8::Object> creationContext) + { + ASSERT(m_scriptState->isolate()->InContext()); + reject(toV8Value(value, creationContext)); + } - template<typename T> - inline void resolve(T* value, ExecutionContext*); - template<typename T> - inline void reject(T* value, ExecutionContext*); + v8::Isolate* isolate() const { return m_scriptState->isolate(); } - template<typename T> - void resolve(PassRefPtr<T> value, ExecutionContext* context) { resolve(value.get(), context); } - template<typename T> - void reject(PassRefPtr<T> value, ExecutionContext* context) { reject(value.get(), context); } + void resolve(v8::Handle<v8::Value>); + void reject(v8::Handle<v8::Value>); +private: template<typename T> - inline void resolve(T* value); - template<typename T> - inline void reject(T* value); + v8::Handle<v8::Value> toV8Value(const T& value, v8::Handle<v8::Object> creationContext) + { + return ToV8Value<ScriptPromiseResolver, v8::Handle<v8::Object> >::toV8Value(value, creationContext, m_scriptState->isolate()); + } template<typename T> - void resolve(PassRefPtr<T> value) { resolve(value.get()); } - template<typename T> - void reject(PassRefPtr<T> value) { reject(value.get()); } - - void resolve(ScriptValue); - void reject(ScriptValue); + v8::Handle<v8::Value> toV8Value(const T& value) + { + return ToV8Value<ScriptPromiseResolver, v8::Handle<v8::Object> >::toV8Value(value, m_scriptState->context()->Global(), m_scriptState->isolate()); + } -private: - ScriptPromiseResolver(ScriptPromise); - void resolve(v8::Handle<v8::Value>); - void reject(v8::Handle<v8::Value>); + explicit ScriptPromiseResolver(ScriptState*); - v8::Isolate* m_isolate; - ScriptPromise m_promise; + // FIXME: Remove this once ScriptValue::scriptState() becomes available. + RefPtr<ScriptState> m_scriptState; + ScriptValue m_resolver; }; -template<typename T> -void ScriptPromiseResolver::resolve(T* value, ExecutionContext* context) -{ - ASSERT(m_isolate->InContext()); - v8::Handle<v8::Context> v8Context = toV8Context(context, DOMWrapperWorld::current()); - resolve(value, v8Context->Global()); -} - -template<typename T> -void ScriptPromiseResolver::reject(T* value, ExecutionContext* context) -{ - ASSERT(m_isolate->InContext()); - v8::Handle<v8::Context> v8Context = toV8Context(context, DOMWrapperWorld::current()); - reject(value, v8Context->Global()); -} - -template<typename T> -void ScriptPromiseResolver::resolve(T* value) -{ - ASSERT(m_isolate->InContext()); - resolve(value, v8::Object::New(m_isolate)); -} - -template<typename T> -void ScriptPromiseResolver::reject(T* value) -{ - ASSERT(m_isolate->InContext()); - reject(value, v8::Object::New(m_isolate)); -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverTest.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverTest.cpp index 26b796dd892..8a21cf7896b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverTest.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverTest.cpp @@ -33,7 +33,6 @@ #include "bindings/v8/ScriptPromise.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/custom/V8PromiseCustom.h" #include <gtest/gtest.h> #include <v8.h> @@ -42,132 +41,145 @@ namespace WebCore { namespace { -class ScriptPromiseResolverTest : public testing::Test { +class Function : public ScriptFunction { public: - ScriptPromiseResolverTest() - : m_isolate(v8::Isolate::GetCurrent()) - , m_handleScope(m_isolate) - , m_context(m_isolate, v8::Context::New(m_isolate)) - , m_contextScope(m_context.newLocal(m_isolate)) + static PassOwnPtr<Function> create(v8::Isolate* isolate, String* value) { + return adoptPtr(new Function(isolate, value)); } - void SetUp() + virtual ScriptValue call(ScriptValue value) OVERRIDE { - v8::Handle<v8::Context> context(m_context.newLocal(m_isolate)); - V8PerContextDataHolder::install(context); - m_perContextData = V8PerContextData::create(context); - m_perContextData->init(); - m_promise = ScriptPromise::createPending(); - m_resolver = ScriptPromiseResolver::create(m_promise); + ASSERT(!value.isEmpty()); + *m_value = toCoreString(value.v8Value()->ToString()); + return value; } - void TearDown() - { - m_resolver = 0; - m_promise.clear(); - m_perContextData.clear(); - } +private: + Function(v8::Isolate* isolate, String* value) : ScriptFunction(isolate), m_value(value) { } - V8PromiseCustom::PromiseState state() - { - return V8PromiseCustom::getState(V8PromiseCustom::getInternal(promise())); - } + String* m_value; +}; - v8::Local<v8::Value> result() +class ScriptPromiseResolverTest : public testing::Test { +public: + ScriptPromiseResolverTest() + : m_scope(v8::Isolate::GetCurrent()) { - return V8PromiseCustom::getInternal(promise())->GetInternalField(V8PromiseCustom::InternalResultIndex); + m_resolver = ScriptPromiseResolver::create(m_scope.scriptState()); } - v8::Local<v8::Object> promise() + virtual ~ScriptPromiseResolverTest() { - ASSERT(!m_promise.hasNoValue()); - return m_promise.v8Value().As<v8::Object>(); + // Run all pending microtasks here. + isolate()->RunMicrotasks(); } + v8::Isolate* isolate() { return m_scope.isolate(); } + protected: - v8::Isolate* m_isolate; - v8::HandleScope m_handleScope; - ScopedPersistent<v8::Context> m_context; - v8::Context::Scope m_contextScope; RefPtr<ScriptPromiseResolver> m_resolver; - ScriptPromise m_promise; - OwnPtr<V8PerContextData> m_perContextData; + V8TestingScope m_scope; }; TEST_F(ScriptPromiseResolverTest, initialState) { - EXPECT_TRUE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Pending, state()); - EXPECT_TRUE(result()->IsUndefined()); + ScriptPromise promise = m_resolver->promise(); + ASSERT_FALSE(promise.isEmpty()); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); } TEST_F(ScriptPromiseResolverTest, resolve) { - EXPECT_TRUE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Pending, state()); - EXPECT_TRUE(result()->IsUndefined()); + ScriptPromise promise = m_resolver->promise(); + ASSERT_FALSE(promise.isEmpty()); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); - m_resolver->resolve(ScriptValue(v8::Integer::New(3, m_isolate), m_isolate)); + m_resolver->resolve("hello"); + EXPECT_TRUE(m_resolver->promise().isEmpty()); + isolate()->RunMicrotasks(); - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Fulfilled, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); } TEST_F(ScriptPromiseResolverTest, reject) { - EXPECT_TRUE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Pending, state()); - EXPECT_TRUE(result()->IsUndefined()); + ScriptPromise promise = m_resolver->promise(); + ASSERT_FALSE(promise.isEmpty()); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); - m_resolver->reject(ScriptValue(v8::Integer::New(3, m_isolate), m_isolate)); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Rejected, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); + m_resolver->reject("hello"); + EXPECT_TRUE(m_resolver->promise().isEmpty()); + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ("hello", onRejected); } TEST_F(ScriptPromiseResolverTest, resolveOverResolve) { - EXPECT_TRUE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Pending, state()); - EXPECT_TRUE(result()->IsUndefined()); - - m_resolver->resolve(ScriptValue(v8::Integer::New(3, m_isolate), m_isolate)); - - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Fulfilled, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); - - m_resolver->resolve(ScriptValue(v8::Integer::New(4, m_isolate), m_isolate)); - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Fulfilled, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); + ScriptPromise promise = m_resolver->promise(); + ASSERT_FALSE(promise.isEmpty()); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + m_resolver->resolve("hello"); + EXPECT_TRUE(m_resolver->promise().isEmpty()); + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); + + m_resolver->resolve("world"); + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); } TEST_F(ScriptPromiseResolverTest, rejectOverResolve) { - EXPECT_TRUE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Pending, state()); - EXPECT_TRUE(result()->IsUndefined()); - - m_resolver->resolve(ScriptValue(v8::Integer::New(3, m_isolate), m_isolate)); - - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Fulfilled, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); - - m_resolver->reject(ScriptValue(v8::Integer::New(4, m_isolate), m_isolate)); - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Fulfilled, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); + ScriptPromise promise = m_resolver->promise(); + ASSERT_FALSE(promise.isEmpty()); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + m_resolver->resolve("hello"); + EXPECT_TRUE(m_resolver->promise().isEmpty()); + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); + + m_resolver->reject("world"); + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); } } // namespace diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.cpp new file mode 100644 index 00000000000..6cd7ab8b5ef --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.cpp @@ -0,0 +1,101 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" + +#include "bindings/v8/V8RecursionScope.h" + +namespace WebCore { + +ScriptPromiseResolverWithContext::ScriptPromiseResolverWithContext(ScriptState* scriptState) + : ActiveDOMObject(scriptState->executionContext()) + , m_state(Pending) + , m_scriptState(scriptState) + , m_mode(Default) + , m_timer(this, &ScriptPromiseResolverWithContext::onTimerFired) + , m_resolver(ScriptPromiseResolver::create(m_scriptState.get())) +#if ASSERTION_ENABLED + , m_isPromiseCalled(false) +#endif +{ + if (executionContext()->activeDOMObjectsAreStopped()) + m_state = ResolvedOrRejected; +} + +void ScriptPromiseResolverWithContext::suspend() +{ + m_timer.stop(); +} + +void ScriptPromiseResolverWithContext::resume() +{ + if (m_state == Resolving || m_state == Rejecting) + m_timer.startOneShot(0, FROM_HERE); +} + +void ScriptPromiseResolverWithContext::stop() +{ + m_timer.stop(); + clear(); +} + +void ScriptPromiseResolverWithContext::keepAliveWhilePending() +{ + if (m_state == ResolvedOrRejected || m_mode == KeepAliveWhilePending) + return; + + // Keep |this| while the promise is Pending. + // deref() will be called in clear(). + m_mode = KeepAliveWhilePending; + ref(); +} + +void ScriptPromiseResolverWithContext::onTimerFired(Timer<ScriptPromiseResolverWithContext>*) +{ + ScriptState::Scope scope(m_scriptState.get()); + resolveOrRejectImmediately(); +} + +void ScriptPromiseResolverWithContext::resolveOrRejectImmediately() +{ + ASSERT(!executionContext()->activeDOMObjectsAreStopped()); + ASSERT(!executionContext()->activeDOMObjectsAreSuspended()); + { + // FIXME: The V8RecursionScope is only necessary to force microtask delivery for promises + // resolved or rejected in workers. It can be removed once worker threads run microtasks + // at the end of every task (rather than just the main thread). + V8RecursionScope scope(m_scriptState->isolate(), m_scriptState->executionContext()); + if (m_state == Resolving) { + m_resolver->resolve(m_value.newLocal(m_scriptState->isolate())); + } else { + ASSERT(m_state == Rejecting); + m_resolver->reject(m_value.newLocal(m_scriptState->isolate())); + } + } + clear(); +} + +void ScriptPromiseResolverWithContext::clear() +{ + if (m_state == ResolvedOrRejected) + return; + ResolutionState state = m_state; + m_state = ResolvedOrRejected; + m_resolver.clear(); + m_value.clear(); + if (m_mode == KeepAliveWhilePending) { + // |ref| was called in |keepAliveWhilePending|. + deref(); + } + // |this| may be deleted here, but it is safe to check |state| because + // it doesn't depend on |this|. When |this| is deleted, |state| can't be + // |Resolving| nor |Rejecting| and hence |this->deref()| can't be executed. + if (state == Resolving || state == Rejecting) { + // |ref| was called in |resolveOrReject|. + deref(); + } +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.h new file mode 100644 index 00000000000..729fb15beed --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.h @@ -0,0 +1,145 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ScriptPromiseResolverWithContext_h +#define ScriptPromiseResolverWithContext_h + +#include "bindings/v8/ScopedPersistent.h" +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolver.h" +#include "bindings/v8/ScriptState.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/ActiveDOMObject.h" +#include "core/dom/ExecutionContext.h" +#include "platform/Timer.h" +#include "wtf/RefCounted.h" +#include "wtf/Vector.h" +#include <v8.h> + +namespace WebCore { + +// This class wraps ScriptPromiseResolver and provides the following +// functionalities in addition to ScriptPromiseResolver's. +// - A ScriptPromiseResolverWithContext retains a ScriptState. A caller +// can call resolve or reject from outside of a V8 context. +// - This class is an ActiveDOMObject and keeps track of the associated +// ExecutionContext state. When the ExecutionContext is suspended, +// resolve or reject will be delayed. When it is stopped, resolve or reject +// will be ignored. +class ScriptPromiseResolverWithContext : public ActiveDOMObject, public RefCounted<ScriptPromiseResolverWithContext> { + WTF_MAKE_NONCOPYABLE(ScriptPromiseResolverWithContext); + +public: + static PassRefPtr<ScriptPromiseResolverWithContext> create(ScriptState* scriptState) + { + RefPtr<ScriptPromiseResolverWithContext> resolver = adoptRef(new ScriptPromiseResolverWithContext(scriptState)); + resolver->suspendIfNeeded(); + return resolver.release(); + } + + virtual ~ScriptPromiseResolverWithContext() + { + // This assertion fails if: + // - promise() is called at least once and + // - this resolver is destructed before it is resolved, rejected or + // the associated ExecutionContext is stopped. + ASSERT(m_state == ResolvedOrRejected || !m_isPromiseCalled); + } + + // Anything that can be passed to toV8Value can be passed to this function. + template <typename T> + void resolve(T value) + { + resolveOrReject(value, Resolving); + } + + // Anything that can be passed to toV8Value can be passed to this function. + template <typename T> + void reject(T value) + { + resolveOrReject(value, Rejecting); + } + + ScriptState* scriptState() { return m_scriptState.get(); } + + // Note that an empty ScriptPromise will be returned after resolve or + // reject is called. + ScriptPromise promise() + { +#if ASSERT_ENABLED + m_isPromiseCalled = true; +#endif + return m_resolver ? m_resolver->promise() : ScriptPromise(); + } + + ScriptState* scriptState() const { return m_scriptState.get(); } + + // ActiveDOMObject implementation. + virtual void suspend() OVERRIDE; + virtual void resume() OVERRIDE; + virtual void stop() OVERRIDE; + + // Once this function is called this resolver stays alive while the + // promise is pending and the associated ExecutionContext isn't stopped. + void keepAliveWhilePending(); + +protected: + // You need to call suspendIfNeeded after the construction because + // this is an ActiveDOMObject. + explicit ScriptPromiseResolverWithContext(ScriptState*); + +private: + enum ResolutionState { + Pending, + Resolving, + Rejecting, + ResolvedOrRejected, + }; + enum LifetimeMode { + Default, + KeepAliveWhilePending, + }; + + template<typename T> + v8::Handle<v8::Value> toV8Value(const T& value) + { + return ToV8Value<ScriptPromiseResolverWithContext, v8::Handle<v8::Object> >::toV8Value(value, m_scriptState->context()->Global(), m_scriptState->isolate()); + } + + template <typename T> + void resolveOrReject(T value, ResolutionState newState) + { + if (m_state != Pending || !executionContext() || executionContext()->activeDOMObjectsAreStopped()) + return; + ASSERT(newState == Resolving || newState == Rejecting); + m_state = newState; + // Retain this object until it is actually resolved or rejected. + // |deref| will be called in |clear|. + ref(); + + ScriptState::Scope scope(m_scriptState.get()); + m_value.set(m_scriptState->isolate(), toV8Value(value)); + if (!executionContext()->activeDOMObjectsAreSuspended()) + resolveOrRejectImmediately(); + } + + void resolveOrRejectImmediately(); + void onTimerFired(Timer<ScriptPromiseResolverWithContext>*); + void clear(); + + ResolutionState m_state; + const RefPtr<ScriptState> m_scriptState; + LifetimeMode m_mode; + Timer<ScriptPromiseResolverWithContext> m_timer; + RefPtr<ScriptPromiseResolver> m_resolver; + ScopedPersistent<v8::Value> m_value; +#if ASSERT_ENABLED + // True if promise() is called. + bool m_isPromiseCalled; +#endif +}; + +} // namespace WebCore + +#endif // #ifndef ScriptPromiseResolverWithContext_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseTest.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseTest.cpp new file mode 100644 index 00000000000..618b38ea91b --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseTest.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "bindings/v8/ScriptPromise.h" + +#include "bindings/v8/ScriptFunction.h" +#include "bindings/v8/ScriptPromiseResolver.h" +#include "bindings/v8/ScriptValue.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/DOMException.h" +#include "core/dom/ExceptionCode.h" + +#include <gtest/gtest.h> +#include <v8.h> + +namespace WebCore { + +namespace { + +void callback(const v8::FunctionCallbackInfo<v8::Value>& info) { } + +class Function : public ScriptFunction { +public: + static PassOwnPtr<Function> create(v8::Isolate* isolate, String* value) + { + return adoptPtr(new Function(isolate, value)); + } + + virtual ScriptValue call(ScriptValue value) OVERRIDE + { + ASSERT(!value.isEmpty()); + *m_value = toCoreString(value.v8Value()->ToString()); + return value; + } + +private: + Function(v8::Isolate* isolate, String* value) : ScriptFunction(isolate), m_value(value) { } + + String* m_value; +}; + +class ScriptPromiseTest : public testing::Test { +public: + ScriptPromiseTest() + : m_scope(v8::Isolate::GetCurrent()) + { + } + + ~ScriptPromiseTest() + { + // FIXME: We put this statement here to clear an exception from the isolate. + createClosure(callback, v8::Undefined(m_scope.isolate()), m_scope.isolate()); + + // Execute all pending microtasks + isolate()->RunMicrotasks(); + } + + ScriptState* scriptState() const { return m_scope.scriptState(); } + v8::Isolate* isolate() const { return m_scope.isolate(); } + +protected: + V8TestingScope m_scope; +}; + +TEST_F(ScriptPromiseTest, constructFromNonPromise) +{ + v8::TryCatch trycatch; + ScriptPromise promise(scriptState(), v8::Undefined(isolate())); + ASSERT_TRUE(trycatch.HasCaught()); + ASSERT_TRUE(promise.isEmpty()); +} + +TEST_F(ScriptPromiseTest, thenResolve) +{ + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState()); + ScriptPromise promise = resolver->promise(); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + resolver->resolve("hello"); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); +} + +TEST_F(ScriptPromiseTest, resolveThen) +{ + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState()); + ScriptPromise promise = resolver->promise(); + String onFulfilled, onRejected; + resolver->resolve("hello"); + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); +} + +TEST_F(ScriptPromiseTest, thenReject) +{ + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState()); + ScriptPromise promise = resolver->promise(); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + resolver->reject("hello"); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ("hello", onRejected); +} + +TEST_F(ScriptPromiseTest, rejectThen) +{ + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState()); + ScriptPromise promise = resolver->promise(); + String onFulfilled, onRejected; + resolver->reject("hello"); + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ("hello", onRejected); +} + +TEST_F(ScriptPromiseTest, castPromise) +{ + ScriptPromise promise = ScriptPromiseResolver::create(scriptState())->promise(); + ScriptPromise newPromise = ScriptPromise::cast(scriptState(), promise.v8Value()); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(promise.v8Value(), newPromise.v8Value()); +} + +TEST_F(ScriptPromiseTest, castNonPromise) +{ + String onFulfilled1, onFulfilled2, onRejected1, onRejected2; + + ScriptValue value = ScriptValue(scriptState(), v8String(isolate(), "hello")); + ScriptPromise promise1 = ScriptPromise::cast(scriptState(), ScriptValue(value)); + ScriptPromise promise2 = ScriptPromise::cast(scriptState(), ScriptValue(value)); + promise1.then(Function::create(isolate(), &onFulfilled1), Function::create(isolate(), &onRejected1)); + promise2.then(Function::create(isolate(), &onFulfilled2), Function::create(isolate(), &onRejected2)); + + ASSERT_FALSE(promise1.isEmpty()); + ASSERT_FALSE(promise2.isEmpty()); + EXPECT_NE(promise1.v8Value(), promise2.v8Value()); + + ASSERT_TRUE(promise1.v8Value()->IsPromise()); + ASSERT_TRUE(promise2.v8Value()->IsPromise()); + + EXPECT_EQ(String(), onFulfilled1); + EXPECT_EQ(String(), onFulfilled2); + EXPECT_EQ(String(), onRejected1); + EXPECT_EQ(String(), onRejected2); + + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled1); + EXPECT_EQ("hello", onFulfilled2); + EXPECT_EQ(String(), onRejected1); + EXPECT_EQ(String(), onRejected2); +} + +TEST_F(ScriptPromiseTest, reject) +{ + String onFulfilled, onRejected; + + ScriptValue value = ScriptValue(scriptState(), v8String(isolate(), "hello")); + ScriptPromise promise = ScriptPromise::reject(scriptState(), ScriptValue(value)); + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + ASSERT_TRUE(promise.v8Value()->IsPromise()); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ("hello", onRejected); +} + +TEST_F(ScriptPromiseTest, rejectWithExceptionState) +{ + String onFulfilled, onRejected; + ScriptPromise promise = ScriptPromise::rejectWithDOMException(scriptState(), DOMException::create(SyntaxError, "some syntax error")); + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ("SyntaxError: some syntax error", onRejected); +} + +} // namespace + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptRegexp.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptRegexp.cpp index d0be2a1ec28..b4e25188288 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptRegexp.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptRegexp.cpp @@ -31,7 +31,8 @@ #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8PerIsolateData.h" -#include "bindings/v8/V8RecursionScope.h" +#include "bindings/v8/V8ScriptRunner.h" +#include "core/dom/ScriptForbiddenScope.h" namespace WebCore { @@ -39,8 +40,8 @@ ScriptRegexp::ScriptRegexp(const String& pattern, TextCaseSensitivity caseSensit { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); - v8::Local<v8::Context> context = V8PerIsolateData::from(isolate)->ensureRegexContext(); - v8::Context::Scope scope(context); + v8::Context::Scope contextScope(V8PerIsolateData::from(isolate)->ensureScriptRegexpContext()); + v8::TryCatch tryCatch; unsigned flags = v8::RegExp::kNone; if (caseSensitivity == TextCaseInsensitive) @@ -48,8 +49,7 @@ ScriptRegexp::ScriptRegexp(const String& pattern, TextCaseSensitivity caseSensit if (multilineMode == MultilineEnabled) flags |= v8::RegExp::kMultiline; - v8::TryCatch tryCatch; - v8::Local<v8::RegExp> regex = v8::RegExp::New(v8String(context->GetIsolate(), pattern), static_cast<v8::RegExp::Flags>(flags)); + v8::Local<v8::RegExp> regex = v8::RegExp::New(v8String(isolate, pattern), static_cast<v8::RegExp::Flags>(flags)); // If the regex failed to compile we'll get an empty handle. if (!regex.IsEmpty()) @@ -68,19 +68,20 @@ int ScriptRegexp::match(const String& string, int startFrom, int* matchLength) c if (string.length() > INT_MAX) return -1; + ScriptForbiddenScope::AllowUserAgentScript allowScript; + v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); - v8::Local<v8::Context> context = V8PerIsolateData::current()->ensureRegexContext(); - v8::Context::Scope scope(context); + v8::Context::Scope contextScope(V8PerIsolateData::from(isolate)->ensureScriptRegexpContext()); v8::TryCatch tryCatch; - V8RecursionScope::MicrotaskSuppression microtaskScope; - v8::Local<v8::RegExp> regex = m_regex.newLocal(isolate); v8::Local<v8::Function> exec = regex->Get(v8AtomicString(isolate, "exec")).As<v8::Function>(); + v8::Handle<v8::Value> argv[] = { v8String(isolate, string.substring(startFrom)) }; + v8::Local<v8::Value> returnValue = V8ScriptRunner::callInternalFunction(exec, regex, WTF_ARRAY_LENGTH(argv), argv, isolate); - v8::Handle<v8::Value> argv[] = { v8String(context->GetIsolate(), string.substring(startFrom)) }; - v8::Local<v8::Value> returnValue = exec->Call(regex, 1, argv); + if (tryCatch.HasCaught()) + return -1; // RegExp#exec returns null if there's no match, otherwise it returns an // Array of strings with the first being the whole match string and others @@ -89,12 +90,12 @@ int ScriptRegexp::match(const String& string, int startFrom, int* matchLength) c // // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec + ASSERT(!returnValue.IsEmpty()); if (!returnValue->IsArray()) return -1; v8::Local<v8::Array> result = returnValue.As<v8::Array>(); int matchOffset = result->Get(v8AtomicString(isolate, "index"))->ToInt32()->Value(); - if (matchLength) { v8::Local<v8::String> match = result->Get(0).As<v8::String>(); *matchLength = match->Length(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.cpp deleted file mode 100644 index 70815114cae..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "bindings/v8/ScriptScope.h" - -#include "bindings/v8/ScriptState.h" -#include "wtf/Assertions.h" - -#include <v8.h> - -namespace WebCore { - -ScriptScope::ScriptScope(ScriptState* scriptState, bool reportExceptions) - : m_handleScope(scriptState->isolate()) - , m_context(scriptState->context()) - , m_scope(m_context) -{ - m_exceptionCatcher.SetVerbose(reportExceptions); - ASSERT(!m_context.IsEmpty()); -} - -bool ScriptScope::success() -{ - if (!m_exceptionCatcher.HasCaught()) - return true; - m_exceptionCatcher.Reset(); - return false; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.h deleted file mode 100644 index ed2cf2f2e87..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ScriptScope_h -#define ScriptScope_h - -#include <v8.h> - -namespace WebCore { - class ScriptState; - - class ScriptScope { - public: - ScriptScope(ScriptState* scriptState, bool reportExceptions = true); - bool success(); - - v8::Local<v8::Object> global() const { return m_context->Global(); } - - private: - v8::HandleScope m_handleScope; - v8::Local<v8::Context> m_context; - v8::Context::Scope m_scope; - v8::TryCatch m_exceptionCatcher; - }; - -} - -#endif // ScriptScope_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptSourceCode.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptSourceCode.h index d5ddbccd082..92944bd9064 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptSourceCode.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptSourceCode.h @@ -38,8 +38,6 @@ #include "wtf/text/TextPosition.h" #include "wtf/text/WTFString.h" -#include <v8.h> - namespace WebCore { class ScriptSourceCode { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.cpp index 0eda05f2ce6..5e17e4c6da8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.cpp @@ -1,126 +1,114 @@ -/* - * Copyright (C) 2009, 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #include "config.h" #include "bindings/v8/ScriptState.h" -#include "V8Window.h" -#include "V8WorkerGlobalScope.h" -#include "bindings/v8/ScriptController.h" -#include "bindings/v8/V8HiddenPropertyName.h" -#include "bindings/v8/WorkerScriptController.h" -#include "core/frame/Frame.h" -#include "core/workers/WorkerGlobalScope.h" -#include <v8.h> -#include "wtf/Assertions.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/ExecutionContext.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -ScriptState::ScriptState(v8::Handle<v8::Context> context) - : m_context(context->GetIsolate(), context) - , m_isolate(context->GetIsolate()) +PassRefPtr<ScriptState> ScriptState::create(v8::Handle<v8::Context> context, PassRefPtr<DOMWrapperWorld> world) { - m_context.setWeak(this, &setWeakCallback); + RefPtr<ScriptState> scriptState = adoptRef(new ScriptState(context, world)); + // This ref() is for keeping this ScriptState alive as long as the v8::Context is alive. + // This is deref()ed in the weak callback of the v8::Context. + scriptState->ref(); + return scriptState; +} + +static void weakCallback(const v8::WeakCallbackData<v8::Context, ScriptState>& data) +{ + data.GetValue()->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, 0); + data.GetParameter()->clearContext(); + data.GetParameter()->deref(); +} + +ScriptState::ScriptState(v8::Handle<v8::Context> context, PassRefPtr<DOMWrapperWorld> world) + : m_isolate(context->GetIsolate()) + , m_context(m_isolate, context) + , m_world(world) + , m_perContextData(V8PerContextData::create(context)) +{ + ASSERT(m_world); + m_context.setWeak(this, &weakCallback); + context->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, this); } ScriptState::~ScriptState() { + ASSERT(!m_perContextData); + ASSERT(m_context.isEmpty()); } -DOMWindow* ScriptState::domWindow() const +bool ScriptState::evalEnabled() const { v8::HandleScope handleScope(m_isolate); - return toDOMWindow(m_context.newLocal(m_isolate)); + return context()->IsCodeGenerationFromStringsAllowed(); } -ExecutionContext* ScriptState::executionContext() const +void ScriptState::setEvalEnabled(bool enabled) { v8::HandleScope handleScope(m_isolate); - return toExecutionContext(m_context.newLocal(m_isolate)); + return context()->AllowCodeGenerationFromStrings(enabled); } -ScriptState* ScriptState::forContext(v8::Handle<v8::Context> context) +ScriptValue ScriptState::getFromGlobalObject(const char* name) { - v8::Context::Scope contextScope(context); - - v8::Local<v8::Object> innerGlobal = v8::Local<v8::Object>::Cast(context->Global()->GetPrototype()); - - v8::Local<v8::Value> scriptStateWrapper = innerGlobal->GetHiddenValue(V8HiddenPropertyName::scriptState(context->GetIsolate())); - if (!scriptStateWrapper.IsEmpty() && scriptStateWrapper->IsExternal()) - return static_cast<ScriptState*>(v8::External::Cast(*scriptStateWrapper)->Value()); + v8::HandleScope handleScope(m_isolate); + v8::Local<v8::Value> v8Value = context()->Global()->Get(v8AtomicString(isolate(), name)); + return ScriptValue(this, v8Value); +} - ScriptState* scriptState = new ScriptState(context); - innerGlobal->SetHiddenValue(V8HiddenPropertyName::scriptState(context->GetIsolate()), v8::External::New(context->GetIsolate(), scriptState)); - return scriptState; +ExecutionContext* ScriptState::executionContext() const +{ + v8::HandleScope scope(m_isolate); + return toExecutionContext(context()); } -ScriptState* ScriptState::current() +void ScriptState::setExecutionContext(ExecutionContext*) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Local<v8::Context> context = isolate->GetCurrentContext(); - ASSERT(!context.IsEmpty()); - return ScriptState::forContext(context); + ASSERT_NOT_REACHED(); } -void ScriptState::setWeakCallback(const v8::WeakCallbackData<v8::Context, ScriptState>& data) +LocalDOMWindow* ScriptState::domWindow() const { - delete data.GetParameter(); + v8::HandleScope scope(m_isolate); + return toDOMWindow(context()); } -bool ScriptState::evalEnabled() const +ScriptState* ScriptState::forMainWorld(LocalFrame* frame) { - v8::HandleScope handleScope(m_isolate); - return context()->IsCodeGenerationFromStringsAllowed(); + v8::Isolate* isolate = toIsolate(frame); + v8::HandleScope handleScope(isolate); + return ScriptState::from(toV8Context(frame, DOMWrapperWorld::mainWorld())); } -void ScriptState::setEvalEnabled(bool enabled) +PassRefPtr<ScriptStateForTesting> ScriptStateForTesting::create(v8::Handle<v8::Context> context, PassRefPtr<DOMWrapperWorld> world) { - v8::HandleScope handleScope(m_isolate); - return context()->AllowCodeGenerationFromStrings(enabled); + RefPtr<ScriptStateForTesting> scriptState = adoptRef(new ScriptStateForTesting(context, world)); + // This ref() is for keeping this ScriptState alive as long as the v8::Context is alive. + // This is deref()ed in the weak callback of the v8::Context. + scriptState->ref(); + return scriptState; } -ScriptState* mainWorldScriptState(Frame* frame) +ScriptStateForTesting::ScriptStateForTesting(v8::Handle<v8::Context> context, PassRefPtr<DOMWrapperWorld> world) + : ScriptState(context, world) { - v8::HandleScope handleScope(toIsolate(frame)); - return ScriptState::forContext(frame->script().mainWorldContext()); } -ScriptState* scriptStateFromWorkerGlobalScope(WorkerGlobalScope* workerGlobalScope) +ExecutionContext* ScriptStateForTesting::executionContext() const { - WorkerScriptController* script = workerGlobalScope->script(); - if (!script) - return 0; + return m_executionContext; +} - v8::HandleScope handleScope(script->isolate()); - return ScriptState::forContext(script->context()); +void ScriptStateForTesting::setExecutionContext(ExecutionContext* executionContext) +{ + m_executionContext = executionContext; } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h index ac93b551167..81bc5840070 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h @@ -1,130 +1,145 @@ -/* - * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #ifndef ScriptState_h #define ScriptState_h #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/V8Utilities.h" +#include "bindings/v8/V8PerContextData.h" +#include "wtf/RefCounted.h" #include <v8.h> -#include "wtf/Noncopyable.h" namespace WebCore { -class DOMWindow; +class LocalDOMWindow; class DOMWrapperWorld; -class Frame; class ExecutionContext; -class WorkerGlobalScope; +class LocalFrame; +class ScriptValue; -class ScriptState { +// ScriptState is created when v8::Context is created. +// ScriptState is destroyed when v8::Context is garbage-collected and +// all V8 proxy objects that have references to the ScriptState are destructed. +class ScriptState : public RefCounted<ScriptState> { WTF_MAKE_NONCOPYABLE(ScriptState); public: - bool hadException() { return !m_exception.isEmpty(); } - void setException(v8::Local<v8::Value> exception) + class Scope { + public: + // You need to make sure that scriptState->context() is not empty before creating a Scope. + explicit Scope(ScriptState* scriptState) + : m_handleScope(scriptState->isolate()) + , m_context(scriptState->context()) + { + ASSERT(!m_context.IsEmpty()); + m_context->Enter(); + } + + ~Scope() + { + m_context->Exit(); + } + + private: + v8::HandleScope m_handleScope; + v8::Handle<v8::Context> m_context; + }; + + static PassRefPtr<ScriptState> create(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); + virtual ~ScriptState(); + + static ScriptState* current(v8::Isolate* isolate) { - m_exception.set(m_isolate, exception); + return from(isolate->GetCurrentContext()); } - v8::Local<v8::Value> exception() { return m_exception.newLocal(m_isolate); } - void clearException() { m_exception.clear(); } - v8::Local<v8::Context> context() const + static ScriptState* from(v8::Handle<v8::Context> context) { - return m_context.newLocal(m_isolate); + ASSERT(!context.IsEmpty()); + ScriptState* scriptState = static_cast<ScriptState*>(context->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex)); + // ScriptState::from() must not be called for a context that does not have + // valid embedder data in the embedder field. + RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState); + RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState->context() == context); + return scriptState; } - v8::Isolate* isolate() - { - return m_isolate; - } + static ScriptState* forMainWorld(LocalFrame*); + + v8::Isolate* isolate() const { return m_isolate; } + DOMWrapperWorld& world() const { return *m_world; } + LocalDOMWindow* domWindow() const; + virtual ExecutionContext* executionContext() const; + virtual void setExecutionContext(ExecutionContext*); + + // This can return an empty handle if the v8::Context is gone. + v8::Handle<v8::Context> context() const { return m_context.newLocal(m_isolate); } + bool contextIsEmpty() const { return m_context.isEmpty(); } + void clearContext() { return m_context.clear(); } + + V8PerContextData* perContextData() const { return m_perContextData.get(); } + void disposePerContextData() { m_perContextData = nullptr; } - DOMWindow* domWindow() const; - ExecutionContext* executionContext() const; bool evalEnabled() const; void setEvalEnabled(bool); - - static ScriptState* forContext(v8::Handle<v8::Context>); - static ScriptState* current(); + ScriptValue getFromGlobalObject(const char* name); protected: - ScriptState() - : m_isolate(v8::Isolate::GetCurrent()) - { - } - - ~ScriptState(); + ScriptState(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); private: - friend ScriptState* mainWorldScriptState(Frame*); - explicit ScriptState(v8::Handle<v8::Context>); + v8::Isolate* m_isolate; + // This persistent handle is weak. + ScopedPersistent<v8::Context> m_context; - static void setWeakCallback(const v8::WeakCallbackData<v8::Context, ScriptState>&); + // This RefPtr doesn't cause a cycle because all persistent handles that DOMWrapperWorld holds are weak. + RefPtr<DOMWrapperWorld> m_world; - ScopedPersistent<v8::Value> m_exception; - ScopedPersistent<v8::Context> m_context; - v8::Isolate* m_isolate; + // This OwnPtr causes a cycle: + // V8PerContextData --(Persistent)--> v8::Context --(RefPtr)--> ScriptState --(OwnPtr)--> V8PerContextData + // So you must explicitly clear the OwnPtr by calling disposePerContextData() + // once you no longer need V8PerContextData. Otherwise, the v8::Context will leak. + OwnPtr<V8PerContextData> m_perContextData; }; -class EmptyScriptState : public ScriptState { +class ScriptStateForTesting : public ScriptState { public: - EmptyScriptState() : ScriptState() { } - ~EmptyScriptState() { } + static PassRefPtr<ScriptStateForTesting> create(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); + + virtual ExecutionContext* executionContext() const OVERRIDE; + virtual void setExecutionContext(ExecutionContext*) OVERRIDE; + +private: + ScriptStateForTesting(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); + + ExecutionContext* m_executionContext; }; -class ScriptStateProtectedPtr { - WTF_MAKE_NONCOPYABLE(ScriptStateProtectedPtr); +// ScriptStateProtectingContext keeps the context associated with the ScriptState alive. +// You need to call clear() once you no longer need the context. Otherwise, the context will leak. +class ScriptStateProtectingContext { + WTF_MAKE_NONCOPYABLE(ScriptStateProtectingContext); public: - ScriptStateProtectedPtr() - : m_scriptState(0) + ScriptStateProtectingContext(ScriptState* scriptState) + : m_scriptState(scriptState) { + if (m_scriptState) + m_context.set(m_scriptState->isolate(), m_scriptState->context()); } - ScriptStateProtectedPtr(ScriptState* scriptState) - : m_scriptState(scriptState) + ScriptState* operator->() const { return m_scriptState.get(); } + ScriptState* get() const { return m_scriptState.get(); } + void clear() { - v8::HandleScope handleScope(scriptState->isolate()); - // Keep the context from being GC'ed. ScriptState is guaranteed to be live while the context is live. - m_context.set(scriptState->isolate(), scriptState->context()); + m_scriptState = nullptr; + m_context.clear(); } - ScriptState* get() const { return m_scriptState; } - private: - ScriptState* m_scriptState; + RefPtr<ScriptState> m_scriptState; ScopedPersistent<v8::Context> m_context; }; -ScriptState* mainWorldScriptState(Frame*); - -ScriptState* scriptStateFromWorkerGlobalScope(WorkerGlobalScope*); - } #endif // ScriptState_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.cpp index fe1ea3ecec2..aa75fde16ad 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.cpp @@ -31,26 +31,53 @@ #include "config.h" #include "bindings/v8/ScriptString.h" +#include "bindings/v8/V8Binding.h" + namespace WebCore { +ScriptString::ScriptString() + : m_isolate(0) +{ +} + +ScriptString::ScriptString(v8::Isolate* isolate, v8::Handle<v8::String> string) + : m_isolate(isolate) + , m_string(SharedPersistent<v8::String>::create(string, m_isolate)) +{ +} + +ScriptString& ScriptString::operator=(const ScriptString& string) +{ + if (this != &string) { + m_isolate = string.m_isolate; + m_string = string.m_string; + } + return *this; +} + +v8::Handle<v8::String> ScriptString::v8Value() +{ + if (isEmpty()) + return v8::Handle<v8::String>(); + return m_string->newLocal(isolate()); +} + ScriptString ScriptString::concatenateWith(const String& string) { v8::Isolate* nonNullIsolate = isolate(); v8::HandleScope handleScope(nonNullIsolate); - v8::Handle<v8::String> b = v8String(nonNullIsolate, string); - if (hasNoValue()) - return ScriptString(b, nonNullIsolate); - v8::Handle<v8::String> a = v8::Handle<v8::String>::Cast(v8Value()); - return ScriptString(v8::String::Concat(a, b), nonNullIsolate); + v8::Handle<v8::String> targetString = v8String(nonNullIsolate, string); + if (isEmpty()) + return ScriptString(nonNullIsolate, targetString); + return ScriptString(nonNullIsolate, v8::String::Concat(v8Value(), targetString)); } -String ScriptString::flattenToString() const +String ScriptString::flattenToString() { - if (hasNoValue()) + if (isEmpty()) return String(); v8::HandleScope handleScope(isolate()); - v8::Handle<v8::String> value = v8::Handle<v8::String>::Cast(v8Value()); - return v8StringToWebCoreString<String>(value, Externalize); + return v8StringToWebCoreString<String>(v8Value(), Externalize); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.h index ed493f8bf48..2638f44836d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.h @@ -31,19 +31,34 @@ #ifndef ScriptString_h #define ScriptString_h -#include "bindings/v8/ScriptValue.h" -#include "bindings/v8/V8Binding.h" +#include "bindings/v8/SharedPersistent.h" +#include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" +#include <v8.h> namespace WebCore { -class ScriptString : public ScriptValue { +class ScriptString FINAL { public: - ScriptString() { } - ScriptString(v8::Handle<v8::String> value, v8::Isolate* isolate) : ScriptValue(value, isolate) { } + ScriptString(); + ScriptString(v8::Isolate*, v8::Handle<v8::String>); + ScriptString& operator=(const ScriptString&); + v8::Isolate* isolate() + { + if (!m_isolate) + m_isolate = v8::Isolate::GetCurrent(); + return m_isolate; + } + bool isEmpty() const { return !m_string || m_string->isEmpty(); } + void clear() { m_string = nullptr; } + v8::Handle<v8::String> v8Value(); ScriptString concatenateWith(const String&); - String flattenToString() const; + String flattenToString(); + +private: + v8::Isolate* m_isolate; + RefPtr<SharedPersistent<v8::String> > m_string; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.cpp index 04b2287f9c2..bdfbe082258 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "bindings/v8/ScriptValue.h" -#include "bindings/v8/ScriptScope.h" #include "bindings/v8/ScriptState.h" #include "bindings/v8/V8Binding.h" #include "platform/JSONValues.h" @@ -42,88 +41,41 @@ ScriptValue::~ScriptValue() { } -bool ScriptValue::getString(String& result) const +v8::Handle<v8::Value> ScriptValue::v8Value() const { - if (hasNoValue()) - return false; + if (isEmpty()) + return v8::Handle<v8::Value>(); - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Value> string = v8Value(); - if (string.IsEmpty() || !string->IsString()) - return false; - result = toCoreString(string.As<v8::String>()); - return true; -} + ASSERT(isolate()->InContext()); -String ScriptValue::toString() const -{ - v8::TryCatch block; - v8::Handle<v8::String> string = v8Value()->ToString(); - if (block.HasCaught()) - return String(); - return v8StringToWebCoreString<String>(string, DoNotExternalize); + // This is a check to validate that you don't return a ScriptValue to a world different + // from the world that created the ScriptValue. + // Probably this could be: + // if (&m_scriptState->world() == &DOMWrapperWorld::current(isolate())) + // return v8::Handle<v8::Value>(); + // instead of triggering RELEASE_ASSERT. + RELEASE_ASSERT(&m_scriptState->world() == &DOMWrapperWorld::current(isolate())); + return m_value->newLocal(isolate()); } -static PassRefPtr<JSONValue> v8ToJSONValue(v8::Handle<v8::Value> value, int maxDepth, v8::Isolate* isolate) +bool ScriptValue::toString(String& result) const { - if (value.IsEmpty()) { - ASSERT_NOT_REACHED(); - return 0; - } - - if (!maxDepth) - return 0; - maxDepth--; + if (isEmpty()) + return false; - if (value->IsNull() || value->IsUndefined()) - return JSONValue::null(); - if (value->IsBoolean()) - return JSONBasicValue::create(value->BooleanValue()); - if (value->IsNumber()) - return JSONBasicValue::create(value->NumberValue()); - if (value->IsString()) - return JSONString::create(toCoreString(value.As<v8::String>())); - if (value->IsArray()) { - v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); - RefPtr<JSONArray> inspectorArray = JSONArray::create(); - uint32_t length = array->Length(); - for (uint32_t i = 0; i < length; i++) { - v8::Local<v8::Value> value = array->Get(v8::Int32::New(i, isolate)); - RefPtr<JSONValue> element = v8ToJSONValue(value, maxDepth, isolate); - if (!element) - return 0; - inspectorArray->pushValue(element); - } - return inspectorArray; - } - if (value->IsObject()) { - RefPtr<JSONObject> jsonObject = JSONObject::create(); - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); - v8::Local<v8::Array> propertyNames = object->GetPropertyNames(); - uint32_t length = propertyNames->Length(); - for (uint32_t i = 0; i < length; i++) { - v8::Local<v8::Value> name = propertyNames->Get(v8::Int32::New(i, isolate)); - // FIXME(yurys): v8::Object should support GetOwnPropertyNames - if (name->IsString() && !object->HasRealNamedProperty(v8::Handle<v8::String>::Cast(name))) - continue; - RefPtr<JSONValue> propertyValue = v8ToJSONValue(object->Get(name), maxDepth, isolate); - if (!propertyValue) - return 0; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, nameString, name, 0); - jsonObject->setValue(nameString, propertyValue); - } - return jsonObject; - } - ASSERT_NOT_REACHED(); - return 0; + ScriptState::Scope scope(m_scriptState.get()); + v8::Handle<v8::Value> string = v8Value(); + if (string.IsEmpty() || !string->IsString()) + return false; + result = toCoreString(v8::Handle<v8::String>::Cast(string)); + return true; } PassRefPtr<JSONValue> ScriptValue::toJSONValue(ScriptState* scriptState) const { - v8::HandleScope handleScope(scriptState->isolate()); - // v8::Object::GetPropertyNames() expects current context to be not null. - v8::Context::Scope contextScope(scriptState->context()); - return v8ToJSONValue(v8Value(), JSONValue::maxDepth, scriptState->isolate()); + ASSERT(!scriptState->contextIsEmpty()); + ScriptState::Scope scope(scriptState); + return v8ToJSONValue(scriptState->isolate(), v8Value(), JSONValue::maxDepth); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.h index 42b5fe7962b..41c76847987 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.h @@ -31,6 +31,7 @@ #ifndef ScriptValue_h #define ScriptValue_h +#include "bindings/v8/ScriptState.h" #include "bindings/v8/SharedPersistent.h" #include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" @@ -40,26 +41,36 @@ namespace WebCore { class JSONValue; -class ScriptState; class ScriptValue { public: ScriptValue() : m_isolate(0) - { } + , m_scriptState(nullptr) + { + } virtual ~ScriptValue(); - ScriptValue(v8::Handle<v8::Value> value, v8::Isolate* isolate) - : m_isolate(isolate) - , m_value(value.IsEmpty() ? 0 : SharedPersistent<v8::Value>::create(value, isolate)) + ScriptValue(ScriptState* scriptState, v8::Handle<v8::Value> value) + : m_isolate(scriptState->isolate()) + , m_scriptState(scriptState) + , m_value(value.IsEmpty() ? nullptr : SharedPersistent<v8::Value>::create(value, scriptState->isolate())) { + ASSERT(isEmpty() || m_scriptState); } ScriptValue(const ScriptValue& value) : m_isolate(value.m_isolate) + , m_scriptState(value.m_scriptState) , m_value(value.m_value) { + ASSERT(isEmpty() || m_scriptState); + } + + ScriptState* scriptState() const + { + return m_scriptState.get(); } v8::Isolate* isolate() const @@ -69,108 +80,80 @@ public: return m_isolate; } - static ScriptValue createUndefined(v8::Isolate* isolate) - { - return ScriptValue(v8::Undefined(isolate), isolate); - } - - static ScriptValue createNull() - { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - return ScriptValue(v8::Null(isolate), isolate); - } - static ScriptValue createBoolean(bool b) - { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - return ScriptValue(b ? v8::True(isolate) : v8::False(isolate), isolate); - } - ScriptValue& operator=(const ScriptValue& value) { if (this != &value) { - m_value = value.m_value; m_isolate = value.m_isolate; + m_scriptState = value.m_scriptState; + m_value = value.m_value; } return *this; } bool operator==(const ScriptValue& value) const { - if (hasNoValue()) - return value.hasNoValue(); - if (value.hasNoValue()) + if (isEmpty()) + return value.isEmpty(); + if (value.isEmpty()) return false; return *m_value == *value.m_value; } - bool isEqual(ScriptState*, const ScriptValue& value) const + bool operator!=(const ScriptValue& value) const { - return operator==(value); + return !operator==(value); } - // Note: This creates a new local Handle; not to be used in cases where is - // is an efficiency problem. + // This creates a new local Handle; Don't use this in performance-sensitive places. bool isFunction() const { - ASSERT(!hasNoValue()); + ASSERT(!isEmpty()); v8::Handle<v8::Value> value = v8Value(); return !value.IsEmpty() && value->IsFunction(); } - bool operator!=(const ScriptValue& value) const - { - return !operator==(value); - } - - // Note: This creates a new local Handle; not to be used in cases where is - // is an efficiency problem. + // This creates a new local Handle; Don't use this in performance-sensitive places. bool isNull() const { - ASSERT(!hasNoValue()); + ASSERT(!isEmpty()); v8::Handle<v8::Value> value = v8Value(); return !value.IsEmpty() && value->IsNull(); } - // Note: This creates a new local Handle; not to be used in cases where is - // is an efficiency problem. + // This creates a new local Handle; Don't use this in performance-sensitive places. bool isUndefined() const { - ASSERT(!hasNoValue()); + ASSERT(!isEmpty()); v8::Handle<v8::Value> value = v8Value(); return !value.IsEmpty() && value->IsUndefined(); } - // Note: This creates a new local Handle; not to be used in cases where is - // is an efficiency problem. + // This creates a new local Handle; Don't use this in performance-sensitive places. bool isObject() const { - ASSERT(!hasNoValue()); + ASSERT(!isEmpty()); v8::Handle<v8::Value> value = v8Value(); return !value.IsEmpty() && value->IsObject(); } - bool hasNoValue() const + bool isEmpty() const { return !m_value.get() || m_value->isEmpty(); } void clear() { - m_value = 0; - } - - v8::Handle<v8::Value> v8Value() const - { - return m_value.get() ? m_value->newLocal(m_isolate) : v8::Handle<v8::Value>(); + m_value = nullptr; } - bool getString(String& result) const; - String toString() const; + v8::Handle<v8::Value> v8Value() const; + bool toString(String&) const; PassRefPtr<JSONValue> toJSONValue(ScriptState*) const; private: mutable v8::Isolate* m_isolate; + mutable RefPtr<ScriptState> m_scriptState; RefPtr<SharedPersistent<v8::Value> > m_value; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptWrappable.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptWrappable.h index 72ab761ee4f..c81fda0e6e1 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptWrappable.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptWrappable.h @@ -31,9 +31,8 @@ #ifndef ScriptWrappable_h #define ScriptWrappable_h -#include "bindings/v8/UnsafePersistent.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/WrapperTypeInfo.h" +#include "platform/heap/Handle.h" #include <v8.h> // Helper to call webCoreInitializeScriptWrappableForInterface in the global namespace. @@ -45,6 +44,35 @@ template <class C> inline void initializeScriptWrappableHelper(C* object) namespace WebCore { +/** + * ScriptWrappable wraps a V8 object and its WrapperTypeInfo. + * + * ScriptWrappable acts much like a v8::Persistent<> in that it keeps a + * V8 object alive. Under the hood, however, it keeps either a TypeInfo + * object or an actual v8 persistent (or is empty). + * + * The physical state space of ScriptWrappable is: + * - uintptr_t m_wrapperOrTypeInfo; + * - if 0: the ScriptWrappable is uninitialized/empty. + * - if even: a pointer to WebCore::TypeInfo + * - if odd: a pointer to v8::Persistent<v8::Object> + 1. + * + * In other words, one integer represents one of two object pointers, + * depending on its least signficiant bit, plus an uninitialized state. + * This class is meant to mask the logistics behind this. + * + * typeInfo() and newLocalWrapper will return appropriate values (possibly + * 0/empty) in all physical states. + * + * The state transitions are: + * - new: an empty and invalid ScriptWrappable. + * - init (to be called by all subclasses in their constructor): + * needs to call setTypeInfo + * - setTypeInfo: install a WrapperTypeInfo + * - setWrapper: install a v8::Persistent (or empty) + * - disposeWrapper (via setWeakCallback, triggered by V8 garbage collecter): + * remove v8::Persistent and install a TypeInfo of the previous value. + */ class ScriptWrappable { public: ScriptWrappable() : m_wrapperOrTypeInfo(0) { } @@ -77,7 +105,9 @@ public: v8::Local<v8::Object> newLocalWrapper(v8::Isolate* isolate) const { - return unsafePersistent().newLocal(isolate); + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + return v8::Local<v8::Object>::New(isolate, persistent); } const WrapperTypeInfo* typeInfo() @@ -85,102 +115,134 @@ public: if (containsTypeInfo()) return reinterpret_cast<const WrapperTypeInfo*>(m_wrapperOrTypeInfo); - if (containsWrapper()) - return toWrapperTypeInfo(*(unsafePersistent().persistent())); + if (containsWrapper()) { + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + return toWrapperTypeInfo(persistent); + } return 0; } - void setTypeInfo(const WrapperTypeInfo* info) + void setTypeInfo(const WrapperTypeInfo* typeInfo) { - m_wrapperOrTypeInfo = reinterpret_cast<uintptr_t>(info); + m_wrapperOrTypeInfo = reinterpret_cast<uintptr_t>(typeInfo); ASSERT(containsTypeInfo()); } + bool isEqualTo(const v8::Local<v8::Object>& other) const + { + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + return persistent == other; + } + static bool wrapperCanBeStoredInObject(const void*) { return false; } static bool wrapperCanBeStoredInObject(const ScriptWrappable*) { return true; } - static void setWrapperInObject(void*, v8::Handle<v8::Object>, v8::Isolate*, const WrapperConfiguration&) + static ScriptWrappable* fromObject(const void*) { ASSERT_NOT_REACHED(); + return 0; } - static void setWrapperInObject(ScriptWrappable* object, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration) + static ScriptWrappable* fromObject(ScriptWrappable* object) { - object->setWrapper(wrapper, isolate, configuration); + return object; } - static const WrapperTypeInfo* getTypeInfoFromObject(void* object) + bool setReturnValue(v8::ReturnValue<v8::Value> returnValue) { - ASSERT_NOT_REACHED(); - return 0; + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + returnValue.Set(persistent); + return containsWrapper(); } - static const WrapperTypeInfo* getTypeInfoFromObject(ScriptWrappable* object) + void markAsDependentGroup(ScriptWrappable* groupRoot, v8::Isolate* isolate) { - return object->typeInfo(); + ASSERT(containsWrapper()); + ASSERT(groupRoot && groupRoot->containsWrapper()); + + v8::UniqueId groupId(groupRoot->m_wrapperOrTypeInfo); + v8::Persistent<v8::Object> wrapper; + getPersistent(&wrapper); + wrapper.MarkPartiallyDependent(); + isolate->SetObjectGroupId(v8::Persistent<v8::Value>::Cast(wrapper), groupId); } - static void setTypeInfoInObject(void* object, const WrapperTypeInfo* info) + void setReference(const v8::Persistent<v8::Object>& parent, v8::Isolate* isolate) { - ASSERT_NOT_REACHED(); + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + isolate->SetReference(parent, persistent); } - static void setTypeInfoInObject(ScriptWrappable* object, const WrapperTypeInfo* info) + template<typename V8T, typename T> + static void assertWrapperSanity(v8::Local<v8::Object> object, T* objectAsT) { - object->setTypeInfo(info); + ASSERT(objectAsT); + RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(object.IsEmpty() + || object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(objectAsT)); } template<typename V8T, typename T> - static bool setReturnValueWithSecurityCheck(v8::ReturnValue<v8::Value> returnValue, T* object) + static void assertWrapperSanity(void* object, T* objectAsT) { - return ScriptWrappable::getUnsafeWrapperFromObject(object).template setReturnValueWithSecurityCheck<V8T>(returnValue, object); + ASSERT_NOT_REACHED(); } - template<typename T> - static bool setReturnValue(v8::ReturnValue<v8::Value> returnValue, T* object) + template<typename V8T, typename T> + static void assertWrapperSanity(ScriptWrappable* object, T* objectAsT) { - return ScriptWrappable::getUnsafeWrapperFromObject(object).setReturnValue(returnValue); + ASSERT(object); + ASSERT(objectAsT); + v8::Object* value = object->getRawValue(); + RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(value == 0 + || value->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(objectAsT)); } + inline bool containsWrapper() const { return (m_wrapperOrTypeInfo & 1); } + inline bool containsTypeInfo() const { return m_wrapperOrTypeInfo && !(m_wrapperOrTypeInfo & 1); } + protected: ~ScriptWrappable() { - ASSERT(m_wrapperOrTypeInfo); // Assert initialization via init() even if not subsequently wrapped. - m_wrapperOrTypeInfo = 0; // Break UAF attempts to wrap. + // We must not get deleted as long as we contain a wrapper. If this happens, we screwed up ref + // counting somewhere. Crash here instead of crashing during a later gc cycle. + RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!containsWrapper()); + ASSERT(m_wrapperOrTypeInfo); // Assert initialization via init() even if not subsequently wrapped. + m_wrapperOrTypeInfo = 0; // Break UAF attempts to wrap. } private: - // For calling unsafePersistent and getWrapperFromObject. - friend class MinorGCWrapperVisitor; - friend class DOMDataStore; - - UnsafePersistent<v8::Object> unsafePersistent() const + void getPersistent(v8::Persistent<v8::Object>* persistent) const { - v8::Object* object = containsWrapper() ? reinterpret_cast<v8::Object*>(m_wrapperOrTypeInfo & ~1) : 0; - return UnsafePersistent<v8::Object>(object); - } + ASSERT(persistent); - static UnsafePersistent<v8::Object> getUnsafeWrapperFromObject(void*) - { - ASSERT_NOT_REACHED(); - return UnsafePersistent<v8::Object>(); + // Horrible and super unsafe: Cast the Persistent to an Object*, so + // that we can inject the wrapped value. This only works because + // we previously 'stole' the object pointer from a Persistent in + // the setWrapper() method. + *reinterpret_cast<v8::Object**>(persistent) = getRawValue(); } - static UnsafePersistent<v8::Object> getUnsafeWrapperFromObject(ScriptWrappable* object) + inline v8::Object* getRawValue() const { - return object->unsafePersistent(); + v8::Object* object = containsWrapper() ? reinterpret_cast<v8::Object*>(m_wrapperOrTypeInfo & ~1) : 0; + return object; } - inline bool containsWrapper() const { return (m_wrapperOrTypeInfo & 1) == 1; } - inline bool containsTypeInfo() const { return m_wrapperOrTypeInfo && (m_wrapperOrTypeInfo & 1) == 0; } - - inline void disposeWrapper(v8::Local<v8::Object> value, const WrapperTypeInfo* info) + inline void disposeWrapper(v8::Local<v8::Object> wrapper) { ASSERT(containsWrapper()); - ASSERT(value == *unsafePersistent().persistent()); - unsafePersistent().dispose(); - setTypeInfo(info); + + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + + ASSERT(wrapper == persistent); + persistent.Reset(); + setTypeInfo(toWrapperTypeInfo(wrapper)); } // If zero, then this contains nothing, otherwise: @@ -190,18 +252,15 @@ private: static void setWeakCallback(const v8::WeakCallbackData<v8::Object, ScriptWrappable>& data) { - ASSERT(*data.GetParameter()->unsafePersistent().persistent() == data.GetValue()); - - // Note: |object| might not be equal to |data|.GetParameter(), e.g., if ScriptWrappable isn't a left-most base class. - void* object = toNative(data.GetValue()); - const WrapperTypeInfo* info = toWrapperTypeInfo(data.GetValue()); - ASSERT(info->derefObjectFunction); + v8::Persistent<v8::Object> persistent; + data.GetParameter()->getPersistent(&persistent); + ASSERT(persistent == data.GetValue()); + data.GetParameter()->disposeWrapper(data.GetValue()); - data.GetParameter()->disposeWrapper(data.GetValue(), info); // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed // inside data.GetParameter()->deref(), which causes Node destructions. We should // make Node destructions incremental. - info->derefObject(object); + releaseObject(data.GetValue()); } }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.cpp b/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.cpp index 72f35602748..8da614f47cc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.cpp @@ -31,16 +31,16 @@ #include "config.h" #include "bindings/v8/SerializedScriptValue.h" -#include "V8Blob.h" -#include "V8DOMFileSystem.h" -#include "V8File.h" -#include "V8FileList.h" -#include "V8ImageData.h" -#include "V8MessagePort.h" -#include "bindings/v8/ScriptScope.h" -#include "bindings/v8/ScriptState.h" +#include "bindings/core/v8/V8Blob.h" +#include "bindings/core/v8/V8File.h" +#include "bindings/core/v8/V8FileList.h" +#include "bindings/core/v8/V8ImageData.h" +#include "bindings/core/v8/V8MessagePort.h" +#include "bindings/modules/v8/V8DOMFileSystem.h" +#include "bindings/modules/v8/V8Key.h" +#include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" +#include "bindings/v8/WorkerScriptController.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "bindings/v8/custom/V8DataViewCustom.h" @@ -61,6 +61,12 @@ #include "core/html/ImageData.h" #include "core/html/canvas/DataView.h" #include "platform/SharedBuffer.h" +#include "platform/heap/Handle.h" +#include "public/platform/Platform.h" +#include "public/platform/WebBlobInfo.h" +#include "public/platform/WebCrypto.h" +#include "public/platform/WebCryptoKey.h" +#include "public/platform/WebCryptoKeyAlgorithm.h" #include "wtf/ArrayBuffer.h" #include "wtf/ArrayBufferContents.h" #include "wtf/ArrayBufferView.h" @@ -133,6 +139,12 @@ private: // need to rehash after every garbage collection because a key object may have been moved. template<typename G> struct V8HandlePtrHash { + static v8::Handle<G> unsafeHandleFromRawValue(const G* value) + { + const v8::Handle<G>* handle = reinterpret_cast<const v8::Handle<G>*>(&value); + return *handle; + } + static unsigned hash(const G* key) { return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdentityHash()); @@ -186,10 +198,13 @@ enum SerializationTag { DateTag = 'D', // value:double -> Date (ref) MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with transferred MessagePort. NumberTag = 'N', // value:double -> Number - BlobTag = 'b', // url:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref) + BlobTag = 'b', // uuid:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref) + BlobIndexTag = 'i', // index:int32_t -> Blob (ref) FileTag = 'f', // file:RawFile -> File (ref) - DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, url:WebCoreString -> FileSystem (ref) + FileIndexTag = 'e', // index:int32_t -> File (ref) + DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, uuid:WebCoreString -> FileSystem (ref) FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref) + FileListIndexTag = 'L', // length:uint32_t, files:int32_t[length] -> FileList (ref) ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref) ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack; // fills it with the last numProperties name,value pairs pushed onto the deserialization stack @@ -201,6 +216,13 @@ enum SerializationTag { ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> ArrayBuffer (ref) ArrayBufferTransferTag = 't', // index:uint32_t -> ArrayBuffer. For ArrayBuffer transfer ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:uint32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the deserialization stack. + CryptoKeyTag = 'K', // subtag:byte, props, usages:uint32_t, keyDataLength:uint32_t, keyData:byte[keyDataLength] + // If subtag=AesKeyTag: + // props = keyLengthBytes:uint32_t, algorithmId:uint32_t + // If subtag=HmacKeyTag: + // props = keyLengthBytes:uint32_t, hashId:uint32_t + // If subtag=RsaHashedKeyTag: + // props = algorithmId:uint32_t, type:uint32_t, modulusLengthBits:uint32_t, publicExponentLength:uint32_t, publicExponent:byte[publicExponentLength], hashId:uint32_t ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref] GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref) GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref) @@ -226,6 +248,52 @@ enum ArrayBufferViewSubTag { DataViewTag = '?' }; +enum CryptoKeySubTag { + AesKeyTag = 1, + HmacKeyTag = 2, + // ID 3 was used by RsaKeyTag, while still behind experimental flag. + RsaHashedKeyTag = 4, + // Maximum allowed value is 255 +}; + +enum AssymetricCryptoKeyType { + PublicKeyType = 1, + PrivateKeyType = 2, + // Maximum allowed value is 2^32-1 +}; + +enum CryptoKeyAlgorithmTag { + AesCbcTag = 1, + HmacTag = 2, + RsaSsaPkcs1v1_5Tag = 3, + // ID 4 was used by RsaEs, while still behind experimental flag. + Sha1Tag = 5, + Sha256Tag = 6, + Sha384Tag = 7, + Sha512Tag = 8, + AesGcmTag = 9, + RsaOaepTag = 10, + AesCtrTag = 11, + AesKwTag = 12, + // Maximum allowed value is 2^32-1 +}; + +enum CryptoKeyUsage { + // Extractability is not a "usage" in the WebCryptoKeyUsages sense, however + // it fits conveniently into this bitfield. + ExtractableUsage = 1 << 0, + + EncryptUsage = 1 << 1, + DecryptUsage = 1 << 2, + SignUsage = 1 << 3, + VerifyUsage = 1 << 4, + DeriveKeyUsage = 1 << 5, + WrapKeyUsage = 1 << 6, + UnwrapKeyUsage = 1 << 7, + DeriveBitsUsage = 1 << 8, + // Maximum allowed value is 1 << 31 +}; + static bool shouldCheckForCycles(int depth) { ASSERT(depth >= 0); @@ -272,9 +340,8 @@ private: class Writer { WTF_MAKE_NONCOPYABLE(Writer); public: - explicit Writer(v8::Isolate* isolate) + Writer() : m_position(0) - , m_isolate(isolate) { } @@ -392,6 +459,13 @@ public: doWriteUint64(size); } + void writeBlobIndex(int blobIndex) + { + ASSERT(blobIndex >= 0); + append(BlobIndexTag); + doWriteUint32(blobIndex); + } + void writeDOMFileSystem(int type, const String& name, const String& url) { append(DOMFileSystemTag); @@ -406,6 +480,12 @@ public: doWriteFile(file); } + void writeFileIndex(int blobIndex) + { + append(FileIndexTag); + doWriteUint32(blobIndex); + } + void writeFileList(const FileList& fileList) { append(FileListTag); @@ -415,6 +495,45 @@ public: doWriteFile(*fileList.item(i)); } + void writeFileListIndex(const Vector<int>& blobIndices) + { + append(FileListIndexTag); + uint32_t length = blobIndices.size(); + doWriteUint32(length); + for (unsigned i = 0; i < length; ++i) + doWriteUint32(blobIndices[i]); + } + + bool writeCryptoKey(const blink::WebCryptoKey& key) + { + append(static_cast<uint8_t>(CryptoKeyTag)); + + switch (key.algorithm().paramsType()) { + case blink::WebCryptoKeyAlgorithmParamsTypeAes: + doWriteAesKey(key); + break; + case blink::WebCryptoKeyAlgorithmParamsTypeHmac: + doWriteHmacKey(key); + break; + case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: + doWriteRsaHashedKey(key); + break; + case blink::WebCryptoKeyAlgorithmParamsTypeNone: + ASSERT_NOT_REACHED(); + return false; + } + + doWriteKeyUsages(key.usages(), key.extractable()); + + blink::WebVector<uint8_t> keyData; + if (!blink::Platform::current()->crypto()->serializeKeyForClone(key, keyData)) + return false; + + doWriteUint32(keyData.size()); + append(keyData.data(), keyData.size()); + return true; + } + void writeArrayBuffer(const ArrayBuffer& arrayBuffer) { append(ArrayBufferTag); @@ -429,7 +548,7 @@ public: ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byteOffset() == static_cast<const uint8_t*>(arrayBufferView.baseAddress())); #endif - ArrayBufferView::ViewType type = arrayBufferView.getType(); + ArrayBufferView::ViewType type = arrayBufferView.type(); if (type == ArrayBufferView::TypeInt8) append(ByteArrayTag); @@ -544,8 +663,6 @@ public: doWriteUint32(length); } - v8::Isolate* getIsolate() { return m_isolate; } - private: void doWriteFile(const File& file) { @@ -588,6 +705,112 @@ private: doWriteString(stringUTF8.data(), stringUTF8.length()); } + void doWriteHmacKey(const blink::WebCryptoKey& key) + { + ASSERT(key.algorithm().paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeHmac); + + append(static_cast<uint8_t>(HmacKeyTag)); + ASSERT(!(key.algorithm().hmacParams()->lengthBits() % 8)); + doWriteUint32(key.algorithm().hmacParams()->lengthBits() / 8); + doWriteAlgorithmId(key.algorithm().hmacParams()->hash().id()); + } + + void doWriteAesKey(const blink::WebCryptoKey& key) + { + ASSERT(key.algorithm().paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeAes); + + append(static_cast<uint8_t>(AesKeyTag)); + doWriteAlgorithmId(key.algorithm().id()); + // Converting the key length from bits to bytes is lossless and makes + // it fit in 1 byte. + ASSERT(!(key.algorithm().aesParams()->lengthBits() % 8)); + doWriteUint32(key.algorithm().aesParams()->lengthBits() / 8); + } + + void doWriteRsaHashedKey(const blink::WebCryptoKey& key) + { + ASSERT(key.algorithm().rsaHashedParams()); + append(static_cast<uint8_t>(RsaHashedKeyTag)); + + doWriteAlgorithmId(key.algorithm().id()); + + switch (key.type()) { + case blink::WebCryptoKeyTypePublic: + doWriteUint32(PublicKeyType); + break; + case blink::WebCryptoKeyTypePrivate: + doWriteUint32(PrivateKeyType); + break; + case blink::WebCryptoKeyTypeSecret: + ASSERT_NOT_REACHED(); + } + + const blink::WebCryptoRsaHashedKeyAlgorithmParams* params = key.algorithm().rsaHashedParams(); + doWriteUint32(params->modulusLengthBits()); + doWriteUint32(params->publicExponent().size()); + append(params->publicExponent().data(), params->publicExponent().size()); + doWriteAlgorithmId(key.algorithm().rsaHashedParams()->hash().id()); + } + + void doWriteAlgorithmId(blink::WebCryptoAlgorithmId id) + { + switch (id) { + case blink::WebCryptoAlgorithmIdAesCbc: + return doWriteUint32(AesCbcTag); + case blink::WebCryptoAlgorithmIdHmac: + return doWriteUint32(HmacTag); + case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: + return doWriteUint32(RsaSsaPkcs1v1_5Tag); + case blink::WebCryptoAlgorithmIdSha1: + return doWriteUint32(Sha1Tag); + case blink::WebCryptoAlgorithmIdSha256: + return doWriteUint32(Sha256Tag); + case blink::WebCryptoAlgorithmIdSha384: + return doWriteUint32(Sha384Tag); + case blink::WebCryptoAlgorithmIdSha512: + return doWriteUint32(Sha512Tag); + case blink::WebCryptoAlgorithmIdAesGcm: + return doWriteUint32(AesGcmTag); + case blink::WebCryptoAlgorithmIdRsaOaep: + return doWriteUint32(RsaOaepTag); + case blink::WebCryptoAlgorithmIdAesCtr: + return doWriteUint32(AesCtrTag); + case blink::WebCryptoAlgorithmIdAesKw: + return doWriteUint32(AesKwTag); + } + ASSERT_NOT_REACHED(); + } + + void doWriteKeyUsages(const blink::WebCryptoKeyUsageMask usages, bool extractable) + { + // Reminder to update this when adding new key usages. + COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe); + + uint32_t value = 0; + + if (extractable) + value |= ExtractableUsage; + + if (usages & blink::WebCryptoKeyUsageEncrypt) + value |= EncryptUsage; + if (usages & blink::WebCryptoKeyUsageDecrypt) + value |= DecryptUsage; + if (usages & blink::WebCryptoKeyUsageSign) + value |= SignUsage; + if (usages & blink::WebCryptoKeyUsageVerify) + value |= VerifyUsage; + if (usages & blink::WebCryptoKeyUsageDeriveKey) + value |= DeriveKeyUsage; + if (usages & blink::WebCryptoKeyUsageWrapKey) + value |= WrapKeyUsage; + if (usages & blink::WebCryptoKeyUsageUnwrapKey) + value |= UnwrapKeyUsage; + if (usages & blink::WebCryptoKeyUsageDeriveBits) + value |= DeriveBitsUsage; + + doWriteUint32(value); + } + int bytesNeededToWireEncode(uint32_t value) { int bytes = 1; @@ -675,23 +898,22 @@ private: Vector<BufferValueType> m_buffer; unsigned m_position; - v8::Isolate* m_isolate; }; -static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Isolate* isolate) +static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { if (!impl) return v8::Handle<v8::Object>(); - v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate); ASSERT(wrapper->IsObject()); return wrapper.As<v8::Object>(); } -static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Isolate* isolate) +static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { if (!impl) return v8::Handle<v8::ArrayBuffer>(); - v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate); ASSERT(wrapper->IsArrayBuffer()); return wrapper.As<v8::ArrayBuffer>(); } @@ -703,28 +925,28 @@ public: Success, InputError, DataCloneError, - InvalidStateError, - JSException, - JSFailure + JSException }; - Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate) - : m_writer(writer) + Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState) + : m_scriptState(scriptState) + , m_writer(writer) , m_tryCatch(tryCatch) , m_depth(0) , m_status(Success) , m_nextObjectReference(0) + , m_blobInfo(blobInfo) , m_blobDataHandles(blobDataHandles) - , m_isolate(isolate) { ASSERT(!tryCatch.HasCaught()); + v8::Handle<v8::Object> creationContext = m_scriptState->context()->Global(); if (messagePorts) { for (size_t i = 0; i < messagePorts->size(); i++) - m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(), m_writer.getIsolate()), i); + m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(), creationContext, isolate()), i); } if (arrayBuffers) { for (size_t i = 0; i < arrayBuffers->size(); i++) { - v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i).get(), m_writer.getIsolate()); + v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i).get(), creationContext, isolate()); // Coalesce multiple occurences of the same buffer to the first index. if (!m_transferredArrayBuffers.contains(v8ArrayBuffer)) m_transferredArrayBuffers.set(v8ArrayBuffer, i); @@ -732,9 +954,11 @@ public: } } + v8::Isolate* isolate() { return m_scriptState->isolate(); } + Status serialize(v8::Handle<v8::Value> value) { - v8::HandleScope scope(m_isolate); + v8::HandleScope scope(isolate()); m_writer.writeVersion(); StateBase* state = doSerialize(value, 0); while (state) @@ -742,6 +966,8 @@ public: return m_status; } + String errorMessage() { return m_errorMessage; } + // Functions used by serialization states. StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next); @@ -752,12 +978,7 @@ public: StateBase* checkException(StateBase* state) { - return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0; - } - - StateBase* reportFailure(StateBase* state) - { - return handleError(JSFailure, state); + return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0; } StateBase* writeObject(uint32_t numProperties, StateBase* state) @@ -796,10 +1017,6 @@ private: // state. virtual StateBase* advance(Serializer&) = 0; - // Returns 1 if this state is currently serializing a property - // via an accessor and 0 otherwise. - virtual uint32_t execDepth() const { return 0; } - protected: StateBase(v8::Handle<v8::Value> composite, StateBase* next) : m_composite(composite) @@ -813,14 +1030,14 @@ private: }; // Dummy state that is used to signal serialization errors. - class ErrorState : public StateBase { + class ErrorState FINAL : public StateBase { public: ErrorState() : StateBase(v8Undefined(), 0) { } - virtual StateBase* advance(Serializer&) + virtual StateBase* advance(Serializer&) OVERRIDE { delete this; return 0; @@ -860,7 +1077,7 @@ private: if (StateBase* newState = serializer.checkException(this)) return newState; if (propertyName.IsEmpty()) - return serializer.reportFailure(this); + return serializer.handleError(InputError, "Empty property names cannot be cloned.", this); bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>()); if (StateBase* newState = serializer.checkException(this)) return newState; @@ -905,33 +1122,33 @@ private: bool m_nameDone; }; - class ObjectState : public AbstractObjectState { + class ObjectState FINAL : public AbstractObjectState { public: ObjectState(v8::Handle<v8::Object> object, StateBase* next) : AbstractObjectState(object, next) { } - virtual StateBase* advance(Serializer& serializer) + virtual StateBase* advance(Serializer& serializer) OVERRIDE { if (m_propertyNames.IsEmpty()) { m_propertyNames = composite()->GetPropertyNames(); if (StateBase* newState = serializer.checkException(this)) return newState; if (m_propertyNames.IsEmpty()) - return serializer.reportFailure(this); + return serializer.handleError(InputError, "Empty property names cannot be cloned.", nextState()); } return serializeProperties(false, serializer); } protected: - virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) + virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE { return serializer.writeObject(numProperties, this); } }; - class DenseArrayState : public AbstractObjectState { + class DenseArrayState FINAL : public AbstractObjectState { public: DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate) : AbstractObjectState(array, next) @@ -941,7 +1158,7 @@ private: m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); } - virtual StateBase* advance(Serializer& serializer) + virtual StateBase* advance(Serializer& serializer) OVERRIDE { while (m_arrayIndex < m_arrayLength) { v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIndex); @@ -955,7 +1172,7 @@ private: } protected: - virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) + virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE { return serializer.writeDenseArray(numProperties, m_arrayLength, this); } @@ -965,7 +1182,7 @@ private: uint32_t m_arrayLength; }; - class SparseArrayState : public AbstractObjectState { + class SparseArrayState FINAL : public AbstractObjectState { public: SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate) : AbstractObjectState(array, next) @@ -973,13 +1190,13 @@ private: m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); } - virtual StateBase* advance(Serializer& serializer) + virtual StateBase* advance(Serializer& serializer) OVERRIDE { return serializeProperties(false, serializer); } protected: - virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) + virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE { return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this); } @@ -989,7 +1206,7 @@ private: { ASSERT(state); ++m_depth; - return checkComposite(state) ? state : handleError(InputError, state); + return checkComposite(state) ? state : handleError(InputError, "Value being cloned is either cyclic or too deeply nested.", state); } StateBase* pop(StateBase* state) @@ -1001,10 +1218,11 @@ private: return next; } - StateBase* handleError(Status errorStatus, StateBase* state) + StateBase* handleError(Status errorStatus, const String& message, StateBase* state) { ASSERT(errorStatus != Success); m_status = errorStatus; + m_errorMessage = message; while (state) { StateBase* tmp = state->nextState(); delete state; @@ -1056,13 +1274,20 @@ private: m_writer.writeBooleanObject(booleanObject->ValueOf()); } - void writeBlob(v8::Handle<v8::Value> value) + StateBase* writeBlob(v8::Handle<v8::Value> value, StateBase* next) { Blob* blob = V8Blob::toNative(value.As<v8::Object>()); if (!blob) - return; - m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); - m_blobDataHandles.add(blob->uuid(), blob->blobDataHandle()); + return 0; + if (blob->hasBeenClosed()) + return handleError(DataCloneError, "A Blob object has been closed, and could therefore not be cloned.", next); + int blobIndex = -1; + m_blobDataHandles.set(blob->uuid(), blob->blobDataHandle()); + if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex)) + m_writer.writeBlobIndex(blobIndex); + else + m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); + return 0; } StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next) @@ -1071,29 +1296,61 @@ private: if (!fs) return 0; if (!fs->clonable()) - return handleError(DataCloneError, next); + return handleError(DataCloneError, "A FileSystem object could not be cloned.", next); m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string()); return 0; } - void writeFile(v8::Handle<v8::Value> value) + StateBase* writeFile(v8::Handle<v8::Value> value, StateBase* next) { File* file = V8File::toNative(value.As<v8::Object>()); if (!file) - return; - m_writer.writeFile(*file); - m_blobDataHandles.add(file->uuid(), file->blobDataHandle()); + return 0; + if (file->hasBeenClosed()) + return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next); + int blobIndex = -1; + m_blobDataHandles.set(file->uuid(), file->blobDataHandle()); + if (appendFileInfo(file, &blobIndex)) { + ASSERT(blobIndex >= 0); + m_writer.writeFileIndex(blobIndex); + } else { + m_writer.writeFile(*file); + } + return 0; } - void writeFileList(v8::Handle<v8::Value> value) + StateBase* writeFileList(v8::Handle<v8::Value> value, StateBase* next) { FileList* fileList = V8FileList::toNative(value.As<v8::Object>()); if (!fileList) - return; - m_writer.writeFileList(*fileList); + return 0; unsigned length = fileList->length(); - for (unsigned i = 0; i < length; ++i) - m_blobDataHandles.add(fileList->item(i)->uuid(), fileList->item(i)->blobDataHandle()); + Vector<int> blobIndices; + for (unsigned i = 0; i < length; ++i) { + int blobIndex = -1; + const File* file = fileList->item(i); + if (file->hasBeenClosed()) + return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next); + m_blobDataHandles.set(file->uuid(), file->blobDataHandle()); + if (appendFileInfo(file, &blobIndex)) { + ASSERT(!i || blobIndex > 0); + ASSERT(blobIndex >= 0); + blobIndices.append(blobIndex); + } + } + if (!blobIndices.isEmpty()) + m_writer.writeFileListIndex(blobIndices); + else + m_writer.writeFileList(*fileList); + return 0; + } + + bool writeCryptoKey(v8::Handle<v8::Value> value) + { + Key* key = V8Key::toNative(value.As<v8::Object>()); + if (!key) + return false; + return m_writer.writeCryptoKey(key->key()); } void writeImageData(v8::Handle<v8::Value> value) @@ -1118,10 +1375,10 @@ private: if (!arrayBufferView) return 0; if (!arrayBufferView->buffer()) - return handleError(DataCloneError, next); - v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), v8::Handle<v8::Object>(), m_writer.getIsolate()); + return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next); + v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), m_scriptState->context()->Global(), isolate()); if (underlyingBuffer.IsEmpty()) - return handleError(DataCloneError, next); + return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next); StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); if (stateOut) return stateOut; @@ -1146,7 +1403,7 @@ private: if (!arrayBuffer) return 0; if (arrayBuffer->isNeutered()) - return handleError(InvalidStateError, next); + return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next); ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>())); m_writer.writeArrayBuffer(*arrayBuffer); return 0; @@ -1158,7 +1415,7 @@ private: if (!arrayBuffer) return 0; if (arrayBuffer->isNeutered()) - return handleError(DataCloneError, next); + return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next); m_writer.writeTransferredArrayBuffer(index); return 0; } @@ -1181,11 +1438,11 @@ private: if (shouldSerializeDensely(length, propertyNames->Length())) { m_writer.writeGenerateFreshDenseArray(length); - return push(new DenseArrayState(array, propertyNames, next, m_isolate)); + return push(new DenseArrayState(array, propertyNames, next, isolate())); } m_writer.writeGenerateFreshSparseArray(length); - return push(new SparseArrayState(array, propertyNames, next, m_isolate)); + return push(new SparseArrayState(array, propertyNames, next, isolate())); } StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next) @@ -1204,34 +1461,68 @@ private: m_objectPool.set(object, objectReference); } + bool appendBlobInfo(const String& uuid, const String& type, unsigned long long size, int* index) + { + if (!m_blobInfo) + return false; + *index = m_blobInfo->size(); + m_blobInfo->append(blink::WebBlobInfo(uuid, type, size)); + return true; + } + + bool appendFileInfo(const File* file, int* index) + { + if (!m_blobInfo) + return false; + + long long size = -1; + double lastModified = invalidFileTime(); + file->captureSnapshot(size, lastModified); + *index = m_blobInfo->size(); + m_blobInfo->append(blink::WebBlobInfo(file->uuid(), file->path(), file->name(), file->type(), lastModified, size)); + return true; + } + + RefPtr<ScriptState> m_scriptState; Writer& m_writer; v8::TryCatch& m_tryCatch; int m_depth; Status m_status; + String m_errorMessage; typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool; ObjectPool m_objectPool; ObjectPool m_transferredMessagePorts; ObjectPool m_transferredArrayBuffers; uint32_t m_nextObjectReference; + WebBlobInfoArray* m_blobInfo; BlobDataHandleMap& m_blobDataHandles; - v8::Isolate* m_isolate; }; +// Returns true if the provided object is to be considered a 'host object', as used in the +// HTML5 structured clone algorithm. +static bool isHostObject(v8::Handle<v8::Object> object) +{ + // If the object has any internal fields, then we won't be able to serialize or deserialize + // them; conveniently, this is also a quick way to detect DOM wrapper objects, because + // the mechanism for these relies on data stored in these fields. We should + // catch external array data as a special case. + return object->InternalFieldCount() || object->HasIndexedPropertiesInExternalArrayData(); +} + Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next) { m_writer.writeReferenceCount(m_nextObjectReference); uint32_t objectReference; uint32_t arrayBufferIndex; - WrapperWorldType currentWorldType = worldType(m_isolate); if ((value->IsObject() || value->IsDate() || value->IsRegExp()) && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { // Note that IsObject() also detects wrappers (eg, it will catch the things // that we grey and write below). ASSERT(!value->IsString()); m_writer.writeObjectReference(objectReference); - } else if (value.IsEmpty()) - return reportFailure(next); - else if (value->IsUndefined()) + } else if (value.IsEmpty()) { + return handleError(InputError, "The empty property name cannot be cloned.", next); + } else if (value->IsUndefined()) m_writer.writeUndefined(); else if (value->IsNull()) m_writer.writeNull(); @@ -1245,22 +1536,22 @@ Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat m_writer.writeUint32(value->Uint32Value()); else if (value->IsNumber()) m_writer.writeNumber(value.As<v8::Number>()->Value()); - else if (V8ArrayBufferView::hasInstance(value, m_isolate, currentWorldType)) + else if (V8ArrayBufferView::hasInstance(value, isolate())) return writeAndGreyArrayBufferView(value.As<v8::Object>(), next); else if (value->IsString()) writeString(value); - else if (V8MessagePort::hasInstance(value, m_isolate, currentWorldType)) { + else if (V8MessagePort::hasInstance(value, isolate())) { uint32_t messagePortIndex; if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePortIndex)) m_writer.writeTransferredMessagePort(messagePortIndex); else - return handleError(DataCloneError, next); - } else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) + return handleError(DataCloneError, "A MessagePort could not be cloned.", next); + } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) return writeTransferredArrayBuffer(value, arrayBufferIndex, next); else { v8::Handle<v8::Object> jsObject = value.As<v8::Object>(); if (jsObject.IsEmpty()) - return handleError(DataCloneError, next); + return handleError(DataCloneError, "An object could not be cloned.", next); greyObject(jsObject); if (value->IsDate()) m_writer.writeDate(value->NumberValue()); @@ -1272,26 +1563,29 @@ Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat writeBooleanObject(value); else if (value->IsArray()) { return startArrayState(value.As<v8::Array>(), next); - } else if (V8File::hasInstance(value, m_isolate, currentWorldType)) - writeFile(value); - else if (V8Blob::hasInstance(value, m_isolate, currentWorldType)) - writeBlob(value); - else if (V8DOMFileSystem::hasInstance(value, m_isolate, currentWorldType)) + } else if (V8File::hasInstance(value, isolate())) + return writeFile(value, next); + else if (V8Blob::hasInstance(value, isolate())) + return writeBlob(value, next); + else if (V8DOMFileSystem::hasInstance(value, isolate())) return writeDOMFileSystem(value, next); - else if (V8FileList::hasInstance(value, m_isolate, currentWorldType)) - writeFileList(value); - else if (V8ImageData::hasInstance(value, m_isolate, currentWorldType)) + else if (V8FileList::hasInstance(value, isolate())) + return writeFileList(value, next); + else if (V8Key::hasInstance(value, isolate())) { + if (!writeCryptoKey(value)) + return handleError(DataCloneError, "Couldn't serialize key data", next); + } else if (V8ImageData::hasInstance(value, isolate())) writeImageData(value); else if (value->IsRegExp()) writeRegExp(value); - else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType)) + else if (V8ArrayBuffer::hasInstance(value, isolate())) return writeArrayBuffer(value, next); else if (value->IsObject()) { if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError()) - return handleError(DataCloneError, next); + return handleError(DataCloneError, "An object could not be cloned.", next); return startObjectState(jsObject, next); } else - return handleError(DataCloneError, next); + return handleError(DataCloneError, "A value could not be cloned.", next); } return 0; } @@ -1319,12 +1613,13 @@ public: // restoring information about saved objects of composite types. class Reader { public: - Reader(const uint8_t* buffer, int length, v8::Isolate* isolate, const BlobDataHandleMap& blobDataHandles) - : m_buffer(buffer) + Reader(const uint8_t* buffer, int length, const WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, ScriptState* scriptState) + : m_scriptState(scriptState) + , m_buffer(buffer) , m_length(length) , m_position(0) , m_version(0) - , m_isolate(isolate) + , m_blobInfo(blobInfo) , m_blobDataHandles(blobDataHandles) { ASSERT(!(reinterpret_cast<size_t>(buffer) & 1)); @@ -1333,8 +1628,12 @@ public: bool isEof() const { return m_position >= m_length; } - v8::Isolate* isolate() const { return m_isolate; } + ScriptState* scriptState() const { return m_scriptState.get(); } + +private: + v8::Isolate* isolate() const { return m_scriptState->isolate(); } +public: bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator) { SerializationTag tag; @@ -1342,7 +1641,7 @@ public: return false; switch (tag) { case ReferenceCountTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t referenceTableSize; if (!doReadUint32(&referenceTableSize)) @@ -1359,16 +1658,16 @@ public: case PaddingTag: return true; case UndefinedTag: - *value = v8::Undefined(m_isolate); + *value = v8::Undefined(isolate()); break; case NullTag: - *value = v8::Null(m_isolate); + *value = v8::Null(isolate()); break; case TrueTag: - *value = v8BooleanWithCheck(true, m_isolate); + *value = v8Boolean(true, isolate()); break; case FalseTag: - *value = v8BooleanWithCheck(false, m_isolate); + *value = v8Boolean(false, isolate()); break; case TrueObjectTag: *value = v8::BooleanObject::New(true); @@ -1414,12 +1713,14 @@ public: creator.pushObjectReference(*value); break; case BlobTag: - if (!readBlob(value)) + case BlobIndexTag: + if (!readBlob(value, tag == BlobIndexTag)) return false; creator.pushObjectReference(*value); break; case FileTag: - if (!readFile(value)) + case FileIndexTag: + if (!readFile(value, tag == FileIndexTag)) return false; creator.pushObjectReference(*value); break; @@ -1429,7 +1730,13 @@ public: creator.pushObjectReference(*value); break; case FileListTag: - if (!readFileList(value)) + case FileListIndexTag: + if (!readFileList(value, tag == FileListIndexTag)) + return false; + creator.pushObjectReference(*value); + break; + case CryptoKeyTag: + if (!readCryptoKey(value)) return false; creator.pushObjectReference(*value); break; @@ -1475,7 +1782,7 @@ public: break; } case ArrayBufferViewTag: { - if (m_version <= 0) + if (!m_version) return false; if (!readArrayBufferView(value, creator)) return false; @@ -1483,7 +1790,7 @@ public: break; } case ArrayBufferTag: { - if (m_version <= 0) + if (!m_version) return false; if (!readArrayBuffer(value)) return false; @@ -1491,14 +1798,14 @@ public: break; } case GenerateFreshObjectTag: { - if (m_version <= 0) + if (!m_version) return false; if (!creator.newObject()) return false; return true; } case GenerateFreshSparseArrayTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t length; if (!doReadUint32(&length)) @@ -1508,7 +1815,7 @@ public: return true; } case GenerateFreshDenseArrayTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t length; if (!doReadUint32(&length)) @@ -1518,7 +1825,7 @@ public: return true; } case MessagePortTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t index; if (!doReadUint32(&index)) @@ -1528,7 +1835,7 @@ public: break; } case ArrayBufferTransferTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t index; if (!doReadUint32(&index)) @@ -1538,7 +1845,7 @@ public: break; } case ObjectReferenceTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t reference; if (!doReadUint32(&reference)) @@ -1577,8 +1884,6 @@ public: m_version = version; } - v8::Isolate* getIsolate() { return m_isolate; } - private: bool readTag(SerializationTag* tag) { @@ -1609,7 +1914,7 @@ private: return false; if (m_position + length > m_length) return false; - *value = v8::String::NewFromUtf8(m_isolate, reinterpret_cast<const char*>(m_buffer + m_position), v8::String::kNormalString, length); + *value = v8::String::NewFromUtf8(isolate(), reinterpret_cast<const char*>(m_buffer + m_position), v8::String::kNormalString, length); m_position += length; return true; } @@ -1622,7 +1927,7 @@ private: if (m_position + length > m_length) return false; ASSERT(!(m_position & 1)); - *value = v8::String::NewFromTwoByte(m_isolate, reinterpret_cast<const uint16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UChar)); + *value = v8::String::NewFromTwoByte(isolate(), reinterpret_cast<const uint16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UChar)); m_position += length; return true; } @@ -1653,7 +1958,7 @@ private: uint32_t rawValue; if (!doReadUint32(&rawValue)) return false; - *value = v8::Integer::New(static_cast<int32_t>(ZigZag::decode(rawValue)), m_isolate); + *value = v8::Integer::New(isolate(), static_cast<int32_t>(ZigZag::decode(rawValue))); return true; } @@ -1662,7 +1967,7 @@ private: uint32_t rawValue; if (!doReadUint32(&rawValue)) return false; - *value = v8::Integer::NewFromUnsigned(rawValue, m_isolate); + *value = v8::Integer::NewFromUnsigned(isolate(), rawValue); return true; } @@ -1671,7 +1976,7 @@ private: double numberValue; if (!doReadNumber(&numberValue)) return false; - *value = v8DateOrNull(numberValue, m_isolate); + *value = v8DateOrNaN(numberValue, isolate()); return true; } @@ -1680,7 +1985,7 @@ private: double number; if (!doReadNumber(&number)) return false; - *value = v8::Number::New(m_isolate, number); + *value = v8::Number::New(isolate(), number); return true; } @@ -1689,7 +1994,7 @@ private: double number; if (!doReadNumber(&number)) return false; - *value = v8::NumberObject::New(m_isolate, number); + *value = v8::NumberObject::New(isolate(), number); return true; } @@ -1706,13 +2011,13 @@ private: return false; if (m_position + pixelDataLength > m_length) return false; - RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height)); + RefPtrWillBeRawPtr<ImageData> imageData = ImageData::create(IntSize(width, height)); Uint8ClampedArray* pixelArray = imageData->data(); ASSERT(pixelArray); ASSERT(pixelArray->length() >= pixelDataLength); memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); m_position += pixelDataLength; - *value = toV8(imageData.release(), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(imageData.release(), m_scriptState->context()->Global(), isolate()); return true; } @@ -1720,9 +2025,9 @@ private: { uint32_t byteLength; if (!doReadUint32(&byteLength)) - return 0; + return nullptr; if (m_position + byteLength > m_length) - return 0; + return nullptr; const void* bufferStart = m_buffer + m_position; RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(bufferStart, byteLength); arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate()); @@ -1735,7 +2040,7 @@ private: RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer(); if (!arrayBuffer) return false; - *value = toV8(arrayBuffer.release(), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), isolate()); return true; } @@ -1759,60 +2064,62 @@ private: arrayBuffer = V8ArrayBuffer::toNative(arrayBufferV8Value.As<v8::Object>()); if (!arrayBuffer) return false; + + v8::Handle<v8::Object> creationContext = m_scriptState->context()->Global(); switch (subTag) { case ByteArrayTag: - *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate()); break; case UnsignedByteArrayTag: - *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate()); break; case UnsignedByteClampedArrayTag: - *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate()); break; case ShortArrayTag: { uint32_t shortLength = byteLength / sizeof(int16_t); if (shortLength * sizeof(int16_t) != byteLength) return false; - *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), creationContext, isolate()); break; } case UnsignedShortArrayTag: { uint32_t shortLength = byteLength / sizeof(uint16_t); if (shortLength * sizeof(uint16_t) != byteLength) return false; - *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), creationContext, isolate()); break; } case IntArrayTag: { uint32_t intLength = byteLength / sizeof(int32_t); if (intLength * sizeof(int32_t) != byteLength) return false; - *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), creationContext, isolate()); break; } case UnsignedIntArrayTag: { uint32_t intLength = byteLength / sizeof(uint32_t); if (intLength * sizeof(uint32_t) != byteLength) return false; - *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), creationContext, isolate()); break; } case FloatArrayTag: { uint32_t floatLength = byteLength / sizeof(float); if (floatLength * sizeof(float) != byteLength) return false; - *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength), creationContext, isolate()); break; } case DoubleArrayTag: { uint32_t floatLength = byteLength / sizeof(double); if (floatLength * sizeof(double) != byteLength) return false; - *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength), creationContext, isolate()); break; } case DataViewTag: - *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate()); break; default: return false; @@ -1835,21 +2142,35 @@ private: return true; } - bool readBlob(v8::Handle<v8::Value>* value) + bool readBlob(v8::Handle<v8::Value>* value, bool isIndexed) { if (m_version < 3) return false; - String uuid; - String type; - uint64_t size; - if (!readWebCoreString(&uuid)) - return false; - if (!readWebCoreString(&type)) - return false; - if (!doReadUint64(&size)) - return false; - RefPtr<Blob> blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size)); - *value = toV8(blob.release(), v8::Handle<v8::Object>(), m_isolate); + RefPtrWillBeRawPtr<Blob> blob; + if (isIndexed) { + if (m_version < 6) + return false; + ASSERT(m_blobInfo); + uint32_t index; + if (!doReadUint32(&index) || index >= m_blobInfo->size()) + return false; + const blink::WebBlobInfo& info = (*m_blobInfo)[index]; + blob = Blob::create(getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size())); + } else { + ASSERT(!m_blobInfo); + String uuid; + String type; + uint64_t size; + ASSERT(!m_blobInfo); + if (!readWebCoreString(&uuid)) + return false; + if (!readWebCoreString(&type)) + return false; + if (!doReadUint64(&size)) + return false; + blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size)); + } + *value = toV8(blob.release(), m_scriptState->context()->Global(), isolate()); return true; } @@ -1864,42 +2185,108 @@ private: return false; if (!readWebCoreString(&url)) return false; - RefPtr<DOMFileSystem> fs = DOMFileSystem::create(getExecutionContext(), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, url)); - *value = toV8(fs.release(), v8::Handle<v8::Object>(), m_isolate); + DOMFileSystem* fs = DOMFileSystem::create(m_scriptState->executionContext(), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, url)); + *value = toV8(fs, m_scriptState->context()->Global(), isolate()); return true; } - bool readFile(v8::Handle<v8::Value>* value) + bool readFile(v8::Handle<v8::Value>* value, bool isIndexed) { - RefPtr<File> file = doReadFileHelper(); + RefPtrWillBeRawPtr<File> file; + if (isIndexed) { + if (m_version < 6) + return false; + file = readFileIndexHelper(); + } else { + file = readFileHelper(); + } if (!file) return false; - *value = toV8(file.release(), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(file.release(), m_scriptState->context()->Global(), isolate()); return true; } - bool readFileList(v8::Handle<v8::Value>* value) + bool readFileList(v8::Handle<v8::Value>* value, bool isIndexed) { if (m_version < 3) return false; uint32_t length; if (!doReadUint32(&length)) return false; - RefPtr<FileList> fileList = FileList::create(); + RefPtrWillBeRawPtr<FileList> fileList = FileList::create(); for (unsigned i = 0; i < length; ++i) { - RefPtr<File> file = doReadFileHelper(); + RefPtrWillBeRawPtr<File> file; + if (isIndexed) { + if (m_version < 6) + return false; + file = readFileIndexHelper(); + } else { + file = readFileHelper(); + } if (!file) return false; fileList->append(file.release()); } - *value = toV8(fileList.release(), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(fileList.release(), m_scriptState->context()->Global(), isolate()); return true; } - PassRefPtr<File> doReadFileHelper() + bool readCryptoKey(v8::Handle<v8::Value>* value) + { + uint32_t rawKeyType; + if (!doReadUint32(&rawKeyType)) + return false; + + blink::WebCryptoKeyAlgorithm algorithm; + blink::WebCryptoKeyType type = blink::WebCryptoKeyTypeSecret; + + switch (static_cast<CryptoKeySubTag>(rawKeyType)) { + case AesKeyTag: + if (!doReadAesKey(algorithm, type)) + return false; + break; + case HmacKeyTag: + if (!doReadHmacKey(algorithm, type)) + return false; + break; + case RsaHashedKeyTag: + if (!doReadRsaHashedKey(algorithm, type)) + return false; + break; + default: + return false; + } + + blink::WebCryptoKeyUsageMask usages; + bool extractable; + if (!doReadKeyUsages(usages, extractable)) + return false; + + uint32_t keyDataLength; + if (!doReadUint32(&keyDataLength)) + return false; + + if (m_position + keyDataLength > m_length) + return false; + + const uint8_t* keyData = m_buffer + m_position; + m_position += keyDataLength; + + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + if (!blink::Platform::current()->crypto()->deserializeKeyForClone( + algorithm, type, extractable, usages, keyData, keyDataLength, key)) { + return false; + } + + *value = toV8(Key::create(key), m_scriptState->context()->Global(), isolate()); + return true; + } + + PassRefPtrWillBeRawPtr<File> readFileHelper() { if (m_version < 3) - return 0; + return nullptr; + ASSERT(!m_blobInfo); String path; String name; String relativePath; @@ -1909,26 +2296,38 @@ private: uint64_t size = 0; double lastModified = 0; if (!readWebCoreString(&path)) - return 0; + return nullptr; if (m_version >= 4 && !readWebCoreString(&name)) - return 0; + return nullptr; if (m_version >= 4 && !readWebCoreString(&relativePath)) - return 0; + return nullptr; if (!readWebCoreString(&uuid)) - return 0; + return nullptr; if (!readWebCoreString(&type)) - return 0; + return nullptr; if (m_version >= 4 && !doReadUint32(&hasSnapshot)) - return 0; + return nullptr; if (hasSnapshot) { if (!doReadUint64(&size)) - return 0; + return nullptr; if (!doReadNumber(&lastModified)) - return 0; + return nullptr; } return File::create(path, name, relativePath, hasSnapshot > 0, size, lastModified, getOrCreateBlobDataHandle(uuid, type)); } + PassRefPtrWillBeRawPtr<File> readFileIndexHelper() + { + if (m_version < 3) + return nullptr; + ASSERT(m_blobInfo); + uint32_t index; + if (!doReadUint32(&index) || index >= m_blobInfo->size()) + return nullptr; + const blink::WebBlobInfo& info = (*m_blobInfo)[index]; + return File::create(info.filePath(), info.fileName(), info.size(), info.lastModified(), getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size())); + } + template<class T> bool doReadUintHelper(T* value) { @@ -1976,7 +2375,7 @@ private: // the collection of BDH's for blobs to work, which would encourage lifetimes to be considered // when passing ssv's around cross process. At present, we get 'lucky' in some cases because // the blob in the src process happens to still exist at the time the dest process is deserializing. - // For example in sharedWorker.postMesssage(...). + // For example in sharedWorker.postMessage(...). BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid); if (it != m_blobDataHandles.end()) { // make assertions about type and size? @@ -1985,18 +2384,171 @@ private: return BlobDataHandle::create(uuid, type, size); } + bool doReadHmacKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type) + { + uint32_t lengthBytes; + if (!doReadUint32(&lengthBytes)) + return false; + blink::WebCryptoAlgorithmId hash; + if (!doReadAlgorithmId(hash)) + return false; + algorithm = blink::WebCryptoKeyAlgorithm::createHmac(hash, lengthBytes * 8); + type = blink::WebCryptoKeyTypeSecret; + return !algorithm.isNull(); + } + + bool doReadAesKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type) + { + blink::WebCryptoAlgorithmId id; + if (!doReadAlgorithmId(id)) + return false; + uint32_t lengthBytes; + if (!doReadUint32(&lengthBytes)) + return false; + algorithm = blink::WebCryptoKeyAlgorithm::createAes(id, lengthBytes * 8); + type = blink::WebCryptoKeyTypeSecret; + return !algorithm.isNull(); + } + + bool doReadRsaHashedKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type) + { + blink::WebCryptoAlgorithmId id; + if (!doReadAlgorithmId(id)) + return false; + + uint32_t rawType; + if (!doReadUint32(&rawType)) + return false; + + switch (static_cast<AssymetricCryptoKeyType>(rawType)) { + case PublicKeyType: + type = blink::WebCryptoKeyTypePublic; + break; + case PrivateKeyType: + type = blink::WebCryptoKeyTypePrivate; + break; + default: + return false; + } + + uint32_t modulusLengthBits; + if (!doReadUint32(&modulusLengthBits)) + return false; + + uint32_t publicExponentSize; + if (!doReadUint32(&publicExponentSize)) + return false; + + if (m_position + publicExponentSize > m_length) + return false; + + const uint8_t* publicExponent = m_buffer + m_position; + m_position += publicExponentSize; + + blink::WebCryptoAlgorithmId hash; + if (!doReadAlgorithmId(hash)) + return false; + algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed(id, modulusLengthBits, publicExponent, publicExponentSize, hash); + + return !algorithm.isNull(); + } + + bool doReadAlgorithmId(blink::WebCryptoAlgorithmId& id) + { + uint32_t rawId; + if (!doReadUint32(&rawId)) + return false; + + switch (static_cast<CryptoKeyAlgorithmTag>(rawId)) { + case AesCbcTag: + id = blink::WebCryptoAlgorithmIdAesCbc; + return true; + case HmacTag: + id = blink::WebCryptoAlgorithmIdHmac; + return true; + case RsaSsaPkcs1v1_5Tag: + id = blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; + return true; + case Sha1Tag: + id = blink::WebCryptoAlgorithmIdSha1; + return true; + case Sha256Tag: + id = blink::WebCryptoAlgorithmIdSha256; + return true; + case Sha384Tag: + id = blink::WebCryptoAlgorithmIdSha384; + return true; + case Sha512Tag: + id = blink::WebCryptoAlgorithmIdSha512; + return true; + case AesGcmTag: + id = blink::WebCryptoAlgorithmIdAesGcm; + return true; + case RsaOaepTag: + id = blink::WebCryptoAlgorithmIdRsaOaep; + return true; + case AesCtrTag: + id = blink::WebCryptoAlgorithmIdAesCtr; + return true; + case AesKwTag: + id = blink::WebCryptoAlgorithmIdAesKw; + return true; + } + + return false; + } + + bool doReadKeyUsages(blink::WebCryptoKeyUsageMask& usages, bool& extractable) + { + // Reminder to update this when adding new key usages. + COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe); + const uint32_t allPossibleUsages = ExtractableUsage | EncryptUsage | DecryptUsage | SignUsage | VerifyUsage | DeriveKeyUsage | WrapKeyUsage | UnwrapKeyUsage | DeriveBitsUsage; + + uint32_t rawUsages; + if (!doReadUint32(&rawUsages)) + return false; + + // Make sure it doesn't contain an unrecognized usage value. + if (rawUsages & ~allPossibleUsages) + return false; + + usages = 0; + + extractable = rawUsages & ExtractableUsage; + + if (rawUsages & EncryptUsage) + usages |= blink::WebCryptoKeyUsageEncrypt; + if (rawUsages & DecryptUsage) + usages |= blink::WebCryptoKeyUsageDecrypt; + if (rawUsages & SignUsage) + usages |= blink::WebCryptoKeyUsageSign; + if (rawUsages & VerifyUsage) + usages |= blink::WebCryptoKeyUsageVerify; + if (rawUsages & DeriveKeyUsage) + usages |= blink::WebCryptoKeyUsageDeriveKey; + if (rawUsages & WrapKeyUsage) + usages |= blink::WebCryptoKeyUsageWrapKey; + if (rawUsages & UnwrapKeyUsage) + usages |= blink::WebCryptoKeyUsageUnwrapKey; + if (rawUsages & DeriveBitsUsage) + usages |= blink::WebCryptoKeyUsageDeriveBits; + + return true; + } + + RefPtr<ScriptState> m_scriptState; const uint8_t* m_buffer; const unsigned m_length; unsigned m_position; uint32_t m_version; - v8::Isolate* m_isolate; + const WebBlobInfoArray* m_blobInfo; const BlobDataHandleMap& m_blobDataHandles; }; typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray; -class Deserializer : public CompositeCreator { +class Deserializer FINAL : public CompositeCreator { public: Deserializer(Reader& reader, MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents) : m_reader(reader) @@ -2009,35 +2561,36 @@ public: v8::Handle<v8::Value> deserialize() { + v8::Isolate* isolate = m_reader.scriptState()->isolate(); if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValue::wireFormatVersion) - return v8::Null(m_reader.getIsolate()); + return v8::Null(isolate); m_reader.setVersion(m_version); - v8::EscapableHandleScope scope(m_reader.getIsolate()); + v8::EscapableHandleScope scope(isolate); while (!m_reader.isEof()) { if (!doDeserialize()) - return v8::Null(m_reader.getIsolate()); + return v8::Null(isolate); } if (stackDepth() != 1 || m_openCompositeReferenceStack.size()) - return v8::Null(m_reader.getIsolate()); + return v8::Null(isolate); v8::Handle<v8::Value> result = scope.Escape(element(0)); return result; } - virtual bool newSparseArray(uint32_t) + virtual bool newSparseArray(uint32_t) OVERRIDE { - v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), 0); + v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isolate(), 0); openComposite(array); return true; } - virtual bool newDenseArray(uint32_t length) + virtual bool newDenseArray(uint32_t length) OVERRIDE { - v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), length); + v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isolate(), length); openComposite(array); return true; } - virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) + virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) OVERRIDE { if (stackDepth() < 1) return false; @@ -2046,40 +2599,16 @@ public: return true; } - virtual bool completeArray(uint32_t length, v8::Handle<v8::Value>* value) - { - if (length > stackDepth()) - return false; - v8::Local<v8::Array> array; - if (m_version > 0) { - v8::Local<v8::Value> composite; - if (!closeComposite(&composite)) - return false; - array = composite.As<v8::Array>(); - } else { - array = v8::Array::New(m_reader.isolate(), length); - } - if (array.IsEmpty()) - return false; - const int depth = stackDepth() - length; - // The V8 API ensures space exists for any index argument to Set; it will (eg) resize arrays as necessary. - for (unsigned i = 0; i < length; ++i) - array->Set(i, element(depth + i)); - pop(length); - *value = array; - return true; - } - - virtual bool newObject() + virtual bool newObject() OVERRIDE { - v8::Local<v8::Object> object = v8::Object::New(); + v8::Local<v8::Object> object = v8::Object::New(m_reader.scriptState()->isolate()); if (object.IsEmpty()) return false; openComposite(object); return true; } - virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value) + virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value) OVERRIDE { v8::Local<v8::Object> object; if (m_version > 0) { @@ -2087,14 +2616,15 @@ public: if (!closeComposite(&composite)) return false; object = composite.As<v8::Object>(); - } else - object = v8::Object::New(); + } else { + object = v8::Object::New(m_reader.scriptState()->isolate()); + } if (object.IsEmpty()) return false; return initializeObject(object, numProperties, value); } - virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) + virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE { v8::Local<v8::Array> array; if (m_version > 0) { @@ -2103,14 +2633,14 @@ public: return false; array = composite.As<v8::Array>(); } else { - array = v8::Array::New(m_reader.isolate()); + array = v8::Array::New(m_reader.scriptState()->isolate()); } if (array.IsEmpty()) return false; return initializeObject(array, numProperties, value); } - virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) + virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE { v8::Local<v8::Array> array; if (m_version > 0) { @@ -2134,22 +2664,23 @@ public: return true; } - virtual void pushObjectReference(const v8::Handle<v8::Value>& object) + virtual void pushObjectReference(const v8::Handle<v8::Value>& object) OVERRIDE { m_objectPool.append(object); } - virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object) + virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE { if (!m_transferredMessagePorts) return false; if (index >= m_transferredMessagePorts->size()) return false; - *object = toV8(m_transferredMessagePorts->at(index).get(), v8::Handle<v8::Object>(), m_reader.getIsolate()); + v8::Handle<v8::Object> creationContext = m_reader.scriptState()->context()->Global(); + *object = toV8(m_transferredMessagePorts->at(index).get(), creationContext, m_reader.scriptState()->isolate()); return true; } - virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>* object) + virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE { if (!m_arrayBufferContents) return false; @@ -2159,15 +2690,17 @@ public: if (result.IsEmpty()) { RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_arrayBufferContents->at(index)); buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate()); - m_reader.isolate()->AdjustAmountOfExternalAllocatedMemory(buffer->byteLength()); - result = toV8Object(buffer.get(), m_reader.getIsolate()); + v8::Isolate* isolate = m_reader.scriptState()->isolate(); + v8::Handle<v8::Object> creationContext = m_reader.scriptState()->context()->Global(); + isolate->AdjustAmountOfExternalAllocatedMemory(buffer->byteLength()); + result = toV8Object(buffer.get(), creationContext, isolate); m_arrayBuffers[index] = result; } *object = result; return true; } - virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object) + virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object) OVERRIDE { if (reference >= m_objectPool.size()) return false; @@ -2175,7 +2708,7 @@ public: return object; } - virtual uint32_t objectReferenceCount() + virtual uint32_t objectReferenceCount() OVERRIDE { return m_objectPool.size(); } @@ -2253,21 +2786,21 @@ private: } // namespace -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate) +PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate) { - return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, didThrow, isolate)); + return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, 0, exceptionState, isolate)); } PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate) { - bool didThrow; - return adoptRef(new SerializedScriptValue(value, 0, 0, didThrow, isolate, DoNotThrowExceptions)); + TrackExceptionState exceptionState; + return adoptRef(new SerializedScriptValue(value, 0, 0, 0, exceptionState, isolate)); } -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, bool& didThrow, ScriptState* state) +PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate) { - ScriptScope scope(state); - return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, didThrow, state->isolate())); + ASSERT(isolate->InContext()); + return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, blobInfo, exceptionState, isolate)); } PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data) @@ -2296,7 +2829,7 @@ PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& da PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data, v8::Isolate* isolate) { - Writer writer(isolate); + Writer writer; writer.writeWebCoreString(data); String wireData = writer.takeWireString(); return adoptRef(new SerializedScriptValue(wireData)); @@ -2309,12 +2842,7 @@ PassRefPtr<SerializedScriptValue> SerializedScriptValue::create() PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue() { - return nullValue(v8::Isolate::GetCurrent()); -} - -PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue(v8::Isolate* isolate) -{ - Writer writer(isolate); + Writer writer; writer.writeNull(); String wireData = writer.takeWireString(); return adoptRef(new SerializedScriptValue(wireData)); @@ -2344,12 +2872,21 @@ SerializedScriptValue::SerializedScriptValue() { } -inline void neuterBinding(ArrayBuffer* object) +static void neuterArrayBufferInAllWorlds(ArrayBuffer* object) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores(); - for (size_t i = 0; i < allStores.size(); i++) { - v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBuffer>(object, isolate); + if (isMainThread()) { + Vector<RefPtr<DOMWrapperWorld> > worlds; + DOMWrapperWorld::allWorldsInMainThread(worlds); + for (size_t i = 0; i < worlds.size(); i++) { + v8::Handle<v8::Object> wrapper = worlds[i]->domDataStore().get<V8ArrayBuffer>(object, isolate); + if (!wrapper.IsEmpty()) { + ASSERT(wrapper->IsArrayBuffer()); + v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter(); + } + } + } else { + v8::Handle<v8::Object> wrapper = DOMWrapperWorld::current(isolate).domDataStore().get<V8ArrayBuffer>(object, isolate); if (!wrapper.IsEmpty()) { ASSERT(wrapper->IsArrayBuffer()); v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter(); @@ -2357,25 +2894,13 @@ inline void neuterBinding(ArrayBuffer* object) } } -inline void neuterBinding(ArrayBufferView* object) -{ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores(); - for (size_t i = 0; i < allStores.size(); i++) { - v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBufferView>(object, isolate); - if (!wrapper.IsEmpty()) - wrapper->SetIndexedPropertiesToExternalArrayData(0, v8::kExternalByteArray, 0); - } -} - -PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, bool& didThrow, v8::Isolate* isolate) +PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate) { ASSERT(arrayBuffers.size()); for (size_t i = 0; i < arrayBuffers.size(); i++) { if (arrayBuffers[i]->isNeutered()) { - setDOMException(InvalidStateError, isolate); - didThrow = true; + exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is already neutered."); return nullptr; } } @@ -2384,72 +2909,51 @@ PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValu HashSet<ArrayBuffer*> visited; for (size_t i = 0; i < arrayBuffers.size(); i++) { - Vector<RefPtr<ArrayBufferView> > neuteredViews; - if (visited.contains(arrayBuffers[i].get())) continue; visited.add(arrayBuffers[i].get()); - bool result = arrayBuffers[i]->transfer(contents->at(i), neuteredViews); + bool result = arrayBuffers[i]->transfer(contents->at(i)); if (!result) { - setDOMException(InvalidStateError, isolate); - didThrow = true; + exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " could not be transferred."); return nullptr; } - neuterBinding(arrayBuffers[i].get()); - for (size_t j = 0; j < neuteredViews.size(); j++) - neuterBinding(neuteredViews[j].get()); + neuterArrayBufferInAllWorlds(arrayBuffers[i].get()); } return contents.release(); } -SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate, ExceptionPolicy policy) +SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate) : m_externallyAllocatedMemory(0) { - didThrow = false; - Writer writer(isolate); + Writer writer; Serializer::Status status; + String errorMessage; { v8::TryCatch tryCatch; - Serializer serializer(writer, messagePorts, arrayBuffers, m_blobDataHandles, tryCatch, isolate); + Serializer serializer(writer, messagePorts, arrayBuffers, blobInfo, m_blobDataHandles, tryCatch, ScriptState::current(isolate)); status = serializer.serialize(value); if (status == Serializer::JSException) { - didThrow = true; // If there was a JS exception thrown, re-throw it. - if (policy == ThrowExceptions) - tryCatch.ReThrow(); + exceptionState.rethrowV8Exception(tryCatch.Exception()); return; } + errorMessage = serializer.errorMessage(); } switch (status) { case Serializer::InputError: case Serializer::DataCloneError: - // If there was an input error, throw a new exception outside - // of the TryCatch scope. - didThrow = true; - if (policy == ThrowExceptions) - setDOMException(DataCloneError, isolate); - return; - case Serializer::InvalidStateError: - didThrow = true; - if (policy == ThrowExceptions) - setDOMException(InvalidStateError, isolate); - return; - case Serializer::JSFailure: - // If there was a JS failure (but no exception), there's not - // much we can do except for unwinding the C++ stack by - // pretending there was a JS exception. - didThrow = true; + exceptionState.throwDOMException(DataCloneError, errorMessage); return; case Serializer::Success: m_data = writer.takeWireString(); ASSERT(m_data.impl()->hasOneRef()); if (arrayBuffers && arrayBuffers->size()) - m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, didThrow, isolate); + m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, exceptionState, isolate); return; case Serializer::JSException: - // We should never get here because this case was handled above. + ASSERT_NOT_REACHED(); break; } ASSERT_NOT_REACHED(); @@ -2463,10 +2967,10 @@ SerializedScriptValue::SerializedScriptValue(const String& wireData) v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts) { - return deserialize(v8::Isolate::GetCurrent(), messagePorts); + return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0); } -v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts) +v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts, const WebBlobInfoArray* blobInfo) { if (!m_data.impl()) return v8::Null(isolate); @@ -2476,7 +2980,7 @@ v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, M // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The // information stored in m_data isn't even encoded in UTF-16. Instead, // unicode characters are encoded as UTF-8 with two code units per UChar. - Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, m_blobDataHandles); + Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), blobInfo, m_blobDataHandles, ScriptState::current(isolate)); Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get()); // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed. @@ -2485,6 +2989,57 @@ v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, M return deserializer.deserialize(); } +bool SerializedScriptValue::extractTransferables(v8::Local<v8::Value> value, int argumentIndex, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate) +{ + if (isUndefinedOrNull(value)) { + ports.resize(0); + arrayBuffers.resize(0); + return true; + } + + uint32_t length = 0; + if (value->IsArray()) { + v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value); + length = array->Length(); + } else if (toV8Sequence(value, length, isolate).IsEmpty()) { + exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex + 1)); + return false; + } + + v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value); + + // Validate the passed array of transferrables. + for (unsigned i = 0; i < length; ++i) { + v8::Local<v8::Value> transferrable = transferrables->Get(i); + // Validation of non-null objects, per HTML5 spec 10.3.3. + if (isUndefinedOrNull(transferrable)) { + exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " is an untransferable " + (transferrable->IsUndefined() ? "'undefined'" : "'null'") + " value."); + return false; + } + // Validation of Objects implementing an interface, per WebIDL spec 4.1.15. + if (V8MessagePort::hasInstance(transferrable, isolate)) { + RefPtr<MessagePort> port = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable)); + // Check for duplicate MessagePorts. + if (ports.contains(port)) { + exceptionState.throwDOMException(DataCloneError, "Message port at index " + String::number(i) + " is a duplicate of an earlier port."); + return false; + } + ports.append(port.release()); + } else if (V8ArrayBuffer::hasInstance(transferrable, isolate)) { + RefPtr<ArrayBuffer> arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(transferrable)); + if (arrayBuffers.contains(arrayBuffer)) { + exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is a duplicate of an earlier ArrayBuffer."); + return false; + } + arrayBuffers.append(arrayBuffer.release()); + } else { + exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " does not have a transferable type."); + return false; + } + } + return true; +} + void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext() { if (m_externallyAllocatedMemory) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.h b/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.h index 97a73aa04ab..b1064206698 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.h @@ -32,11 +32,16 @@ #define SerializedScriptValue_h #include "bindings/v8/ScriptValue.h" - #include "wtf/HashMap.h" #include "wtf/ThreadSafeRefCounted.h" #include <v8.h> +namespace blink { + +class WebBlobInfo; + +} + namespace WTF { class ArrayBuffer; @@ -47,11 +52,13 @@ class ArrayBufferContents; namespace WebCore { class BlobDataHandle; +class ExceptionState; class MessagePort; typedef Vector<RefPtr<MessagePort>, 1> MessagePortArray; typedef Vector<RefPtr<WTF::ArrayBuffer>, 1> ArrayBufferArray; typedef HashMap<String, RefPtr<BlobDataHandle> > BlobDataHandleMap; +typedef Vector<blink::WebBlobInfo> WebBlobInfoArray; class SerializedScriptValue FINAL : public ThreadSafeRefCounted<SerializedScriptValue> { public: @@ -59,7 +66,9 @@ public: // Version 2: Added StringUCharTag for UChar v8 strings. // Version 3: Switched to using uuids as blob data identifiers. // Version 4: Extended File serialization to be complete. - static const uint32_t wireFormatVersion = 4; + // Version 5: Added CryptoKeyTag for Key objects. + // Version 6: Added indexed serialization for File, Blob, and FileList. + static const uint32_t wireFormatVersion = 6; ~SerializedScriptValue(); @@ -68,20 +77,18 @@ public: // be thrown using v8::ThrowException(), and sets |didThrow|. In this case // the caller must not invoke any V8 operations until control returns to // V8. When serialization is successful, |didThrow| is false. - static PassRefPtr<SerializedScriptValue> create(v8::Handle<v8::Value>, MessagePortArray*, ArrayBufferArray*, bool& didThrow, v8::Isolate*); + static PassRefPtr<SerializedScriptValue> create(v8::Handle<v8::Value>, MessagePortArray*, ArrayBufferArray*, ExceptionState&, v8::Isolate*); static PassRefPtr<SerializedScriptValue> createFromWire(const String&); static PassRefPtr<SerializedScriptValue> createFromWireBytes(const Vector<uint8_t>&); static PassRefPtr<SerializedScriptValue> create(const String&); static PassRefPtr<SerializedScriptValue> create(const String&, v8::Isolate*); static PassRefPtr<SerializedScriptValue> create(); - - static PassRefPtr<SerializedScriptValue> create(const ScriptValue&, bool& didThrow, ScriptState*); + static PassRefPtr<SerializedScriptValue> create(const ScriptValue&, WebBlobInfoArray*, ExceptionState&, v8::Isolate*); // Never throws exceptions. static PassRefPtr<SerializedScriptValue> createAndSwallowExceptions(v8::Handle<v8::Value>, v8::Isolate*); static PassRefPtr<SerializedScriptValue> nullValue(); - static PassRefPtr<SerializedScriptValue> nullValue(v8::Isolate*); String toWireString() const { return m_data; } void toWireBytes(Vector<char>&) const; @@ -89,11 +96,13 @@ public: // Deserializes the value (in the current context). Returns a null value in // case of failure. v8::Handle<v8::Value> deserialize(MessagePortArray* = 0); - v8::Handle<v8::Value> deserialize(v8::Isolate*, MessagePortArray* = 0); + v8::Handle<v8::Value> deserialize(v8::Isolate*, MessagePortArray* = 0, const WebBlobInfoArray* = 0); - // Only reflects the truth if the SSV was created by walking a v8 value, not reliable - // if the SSV was created createdFromWire(data). - bool containsBlobs() const { return !m_blobDataHandles.isEmpty(); } + // Helper function which pulls the values out of a JS sequence and into a MessagePortArray. + // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 + // of the HTML5 spec and generates exceptions as appropriate. + // Returns true if the array was filled, or false if the passed value was not of an appropriate type. + static bool extractTransferables(v8::Local<v8::Value>, int, MessagePortArray&, ArrayBufferArray&, ExceptionState&, v8::Isolate*); // Informs the V8 about external memory allocated and owned by this object. Large values should contribute // to GC counters to eventually trigger a GC, otherwise flood of postMessage() can cause OOM. @@ -106,17 +115,13 @@ private: StringValue, WireData }; - enum ExceptionPolicy { - ThrowExceptions, - DoNotThrowExceptions - }; typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray; SerializedScriptValue(); - SerializedScriptValue(v8::Handle<v8::Value>, MessagePortArray*, ArrayBufferArray*, bool& didThrow, v8::Isolate*, ExceptionPolicy = ThrowExceptions); + SerializedScriptValue(v8::Handle<v8::Value>, MessagePortArray*, ArrayBufferArray*, WebBlobInfoArray*, ExceptionState&, v8::Isolate*); explicit SerializedScriptValue(const String& wireData); - static PassOwnPtr<ArrayBufferContentsArray> transferArrayBuffers(ArrayBufferArray&, bool& didThrow, v8::Isolate*); + static PassOwnPtr<ArrayBufferContentsArray> transferArrayBuffers(ArrayBufferArray&, ExceptionState&, v8::Isolate*); String m_data; OwnPtr<ArrayBufferContentsArray> m_arrayBufferContentsArray; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/UnsafePersistent.h b/chromium/third_party/WebKit/Source/bindings/v8/UnsafePersistent.h deleted file mode 100644 index 4a889c27430..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/UnsafePersistent.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef UnsafePersistent_h -#define UnsafePersistent_h - -#include "bindings/v8/WrapperTypeInfo.h" - -#include <v8.h> - -namespace WebCore { - -template<class KeyType> class DOMWrapperMap; - -// An unsafe way to pass Persistent handles around. Do not use unless you know -// what you're doing. UnsafePersistent is only safe to use when we know that the -// memory pointed by the it is not going away: 1) When GC cannot happen while -// the UnsafePersistent is alive or 2) when there is a strong Persistent keeping -// the memory alive while the UnsafePersistent is alive. -template<typename T> class UnsafePersistent { -public: - UnsafePersistent() : m_value(0) { } - explicit UnsafePersistent(T* value) : m_value(value) { } - explicit UnsafePersistent(v8::Persistent<T>& handle) - { - m_value = handle.ClearAndLeak(); - } - - UnsafePersistent(v8::Isolate* isolate, v8::Handle<T>& handle) - { - v8::Persistent<T> persistent(isolate, handle); - m_value = persistent.ClearAndLeak(); - } - - T* value() const - { - return m_value; - } - - template<typename V8T, typename U> - inline bool setReturnValueWithSecurityCheck(v8::ReturnValue<v8::Value> returnValue, U* object) - { - v8::Handle<v8::Object> result = deprecatedHandle(); - // Security: always guard against malicious tampering. - RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result.IsEmpty() || result->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(object)); - returnValue.Set(result); - return !result.IsEmpty(); - } - - inline bool setReturnValue(v8::ReturnValue<v8::Value> returnValue) - { - returnValue.Set(deprecatedHandle()); - return !isEmpty(); - } - - // This is incredibly unsafe: the handle is valid only when this - // UnsafePersistent is alive and valid (see class level comment). - v8::Persistent<T>* persistent() - { - v8::Persistent<T>* handle = reinterpret_cast<v8::Persistent<T>*>(&m_value); - return handle; - } - - void setReferenceFrom(const v8::Persistent<v8::Object>& parent, v8::Isolate* isolate) - { - isolate->SetReference(parent, *persistent()); - } - - void dispose() - { - persistent()->Reset(); - m_value = 0; - } - - void clear() - { - m_value = 0; - } - - v8::Local<T> newLocal(v8::Isolate* isolate) - { - return v8::Local<T>::New(isolate, *persistent()); - } - - bool isEmpty() const - { - return !m_value; - } - -private: - v8::Handle<T> deprecatedHandle() - { - v8::Handle<T>* handle = reinterpret_cast<v8::Handle<T>*>(&m_value); - return *handle; - } - - T* m_value; -}; - -} // namespace WebCore - -#endif // UnsafePersistent_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.cpp index 5324a0d59c2..12f78db5563 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.cpp @@ -31,23 +31,32 @@ #include "config.h" #include "bindings/v8/V8AbstractEventListener.h" -#include "V8Event.h" -#include "V8EventTarget.h" +#include "bindings/core/v8/V8Event.h" +#include "bindings/core/v8/V8EventTarget.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8EventListenerList.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/events/BeforeUnloadEvent.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" #include "core/inspector/InspectorCounters.h" #include "core/workers/WorkerGlobalScope.h" namespace WebCore { -V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, PassRefPtr<DOMWrapperWorld> world, v8::Isolate* isolate) +V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, ScriptState* scriptState) : EventListener(JSEventListenerType) , m_isAttribute(isAttribute) - , m_world(world) + , m_scriptState(scriptState) + , m_isolate(scriptState->isolate()) +{ + if (isMainThread()) + InspectorCounters::incrementCounter(InspectorCounters::JSEventListenerCounter); +} + +V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, v8::Isolate* isolate) + : EventListener(JSEventListenerType) + , m_isAttribute(isAttribute) + , m_scriptState(nullptr) , m_isolate(isolate) { if (isMainThread()) @@ -58,16 +67,16 @@ V8AbstractEventListener::~V8AbstractEventListener() { if (!m_listener.isEmpty()) { v8::HandleScope scope(m_isolate); - V8EventListenerList::clearWrapper(m_listener.newLocal(m_isolate), m_isAttribute, m_isolate); + V8EventListenerList::clearWrapper(m_listener.newLocal(isolate()), m_isAttribute, isolate()); } if (isMainThread()) InspectorCounters::decrementCounter(InspectorCounters::JSEventListenerCounter); } -void V8AbstractEventListener::handleEvent(ExecutionContext* context, Event* event) +void V8AbstractEventListener::handleEvent(ExecutionContext*, Event* event) { // Don't reenter V8 if execution was terminated in this instance of V8. - if (context->isJSExecutionForbidden()) + if (scriptState()->executionContext()->isJSExecutionForbidden()) return; ASSERT(event); @@ -76,82 +85,68 @@ void V8AbstractEventListener::handleEvent(ExecutionContext* context, Event* even // See issue 889829. RefPtr<V8AbstractEventListener> protect(this); - v8::HandleScope handleScope(m_isolate); - - v8::Local<v8::Context> v8Context = toV8Context(context, world()); - if (v8Context.IsEmpty()) + if (scriptState()->contextIsEmpty()) return; - - // Enter the V8 context in which to perform the event handling. - v8::Context::Scope scope(v8Context); + ScriptState::Scope scope(scriptState()); // Get the V8 wrapper for the event object. - v8::Isolate* isolate = v8Context->GetIsolate(); - v8::Handle<v8::Value> jsEvent = toV8(event, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> jsEvent = toV8(event, scriptState()->context()->Global(), isolate()); if (jsEvent.IsEmpty()) return; - invokeEventHandler(context, event, v8::Local<v8::Value>::New(isolate, jsEvent)); + invokeEventHandler(event, v8::Local<v8::Value>::New(isolate(), jsEvent)); } void V8AbstractEventListener::setListenerObject(v8::Handle<v8::Object> listener) { - m_listener.set(m_isolate, listener); + m_listener.set(isolate(), listener); m_listener.setWeak(this, &setWeakCallback); } -void V8AbstractEventListener::invokeEventHandler(ExecutionContext* context, Event* event, v8::Local<v8::Value> jsEvent) +void V8AbstractEventListener::invokeEventHandler(Event* event, v8::Local<v8::Value> jsEvent) { // If jsEvent is empty, attempt to set it as a hidden value would crash v8. if (jsEvent.IsEmpty()) return; - v8::Local<v8::Context> v8Context = toV8Context(context, world()); - if (v8Context.IsEmpty()) - return; - - // We push the event being processed into the global object, so that it can be exposed by DOMWindow's bindings. - v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(v8Context->GetIsolate()); + ASSERT(!scriptState()->contextIsEmpty()); v8::Local<v8::Value> returnValue; - { // Catch exceptions thrown in the event handler so they do not propagate to javascript code that caused the event to fire. v8::TryCatch tryCatch; tryCatch.SetVerbose(true); // Save the old 'event' property so we can restore it later. - v8::Local<v8::Value> savedEvent = v8Context->Global()->GetHiddenValue(eventSymbol); + v8::Local<v8::Value> savedEvent = V8HiddenValue::getHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate())); tryCatch.Reset(); - // Make the event available in the global object, so DOMWindow can expose it. - v8Context->Global()->SetHiddenValue(eventSymbol, jsEvent); + // Make the event available in the global object, so LocalDOMWindow can expose it. + V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate()), jsEvent); tryCatch.Reset(); - returnValue = callListenerFunction(context, jsEvent, event); + returnValue = callListenerFunction(jsEvent, event); if (tryCatch.HasCaught()) event->target()->uncaughtExceptionInEventHandler(); if (!tryCatch.CanContinue()) { // Result of TerminateExecution(). - if (context->isWorkerGlobalScope()) - toWorkerGlobalScope(context)->script()->forbidExecution(); + if (scriptState()->executionContext()->isWorkerGlobalScope()) + toWorkerGlobalScope(scriptState()->executionContext())->script()->forbidExecution(); return; } tryCatch.Reset(); // Restore the old event. This must be done for all exit paths through this method. if (savedEvent.IsEmpty()) - v8Context->Global()->SetHiddenValue(eventSymbol, v8::Undefined(v8Context->GetIsolate())); + V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate()), v8::Undefined(isolate())); else - v8Context->Global()->SetHiddenValue(eventSymbol, savedEvent); + V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate()), savedEvent); tryCatch.Reset(); } - ASSERT(!handleOutOfMemory() || returnValue.IsEmpty()); - if (returnValue.IsEmpty()) return; - if (!returnValue->IsNull() && !returnValue->IsUndefined() && event->isBeforeUnloadEvent()) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, stringReturnValue, returnValue); + if (m_isAttribute && !returnValue->IsNull() && !returnValue->IsUndefined() && event->isBeforeUnloadEvent()) { + TOSTRING_VOID(V8StringResource<>, stringReturnValue, returnValue); toBeforeUnloadEvent(event)->setReturnValue(stringReturnValue); } @@ -166,18 +161,22 @@ bool V8AbstractEventListener::shouldPreventDefault(v8::Local<v8::Value> returnVa return returnValue->IsBoolean() && !returnValue->BooleanValue(); } -v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(ExecutionContext* context, Event* event) +v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event) { - v8::Isolate* isolate = toV8Context(context, world())->GetIsolate(); - v8::Local<v8::Object> listener = m_listener.newLocal(isolate); + v8::Local<v8::Object> listener = m_listener.newLocal(isolate()); if (!m_listener.isEmpty() && !listener->IsFunction()) return listener; EventTarget* target = event->currentTarget(); - v8::Handle<v8::Value> value = toV8(target, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> value = toV8(target, scriptState()->context()->Global(), isolate()); if (value.IsEmpty()) return v8::Local<v8::Object>(); - return v8::Local<v8::Object>::New(isolate, v8::Handle<v8::Object>::Cast(value)); + return v8::Local<v8::Object>::New(isolate(), v8::Handle<v8::Object>::Cast(value)); +} + +bool V8AbstractEventListener::belongsToTheCurrentWorld() const +{ + return isolate()->InContext() && &world() == &DOMWrapperWorld::current(isolate()); } void V8AbstractEventListener::setWeakCallback(const v8::WeakCallbackData<v8::Object, V8AbstractEventListener> &data) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.h b/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.h index c605821ea67..469050c4207 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.h @@ -33,7 +33,6 @@ #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/V8Utilities.h" #include "core/events/EventListener.h" #include <v8.h> #include "wtf/PassRefPtr.h" @@ -69,9 +68,9 @@ namespace WebCore { // Implementation of EventListener interface. - virtual bool operator==(const EventListener& other) { return this == &other; } + virtual bool operator==(const EventListener& other) OVERRIDE { return this == &other; } - virtual void handleEvent(ExecutionContext*, Event*); + virtual void handleEvent(ExecutionContext*, Event*) OVERRIDE; virtual bool isLazy() const { return false; } @@ -109,26 +108,34 @@ namespace WebCore { m_listener.clear(); } - virtual DOMWrapperWorld* world() const OVERRIDE FINAL { return m_world.get(); } + virtual bool belongsToTheCurrentWorld() const OVERRIDE FINAL; v8::Isolate* isolate() const { return m_isolate; } + virtual DOMWrapperWorld& world() const { return scriptState()->world(); } + ScriptState* scriptState() const + { + ASSERT(m_scriptState); + return m_scriptState.get(); + } + void setScriptState(ScriptState* scriptState) { m_scriptState = scriptState; } protected: - V8AbstractEventListener(bool isAttribute, PassRefPtr<DOMWrapperWorld>, v8::Isolate*); + V8AbstractEventListener(bool isAttribute, ScriptState*); + V8AbstractEventListener(bool isAttribute, v8::Isolate*); virtual void prepareListenerObject(ExecutionContext*) { } void setListenerObject(v8::Handle<v8::Object> listener); - void invokeEventHandler(ExecutionContext*, Event*, v8::Local<v8::Value> jsEvent); + void invokeEventHandler(Event*, v8::Local<v8::Value> jsEvent); // Get the receiver object to use for event listener call. - v8::Local<v8::Object> getReceiverObject(ExecutionContext*, Event*); + v8::Local<v8::Object> getReceiverObject(Event*); private: // Implementation of EventListener function. - virtual bool virtualisAttribute() const { return m_isAttribute; } + virtual bool virtualisAttribute() const OVERRIDE { return m_isAttribute; } - virtual v8::Local<v8::Value> callListenerFunction(ExecutionContext*, v8::Handle<v8::Value> jsevent, Event*) = 0; + virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsevent, Event*) = 0; virtual bool shouldPreventDefault(v8::Local<v8::Value> returnValue); @@ -139,7 +146,10 @@ namespace WebCore { // Indicates if this is an HTML type listener. bool m_isAttribute; - RefPtr<DOMWrapperWorld> m_world; + // For V8LazyEventListener, m_scriptState can be 0 until V8LazyEventListener is actually used. + // m_scriptState is set lazily because V8LazyEventListener doesn't know the associated frame + // until the listener is actually used. + RefPtr<ScriptState> m_scriptState; v8::Isolate* m_isolate; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.cpp index 2d8da03d149..639784e3f56 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.cpp @@ -31,12 +31,14 @@ #include "config.h" #include "bindings/v8/V8Binding.h" -#include "V8Element.h" -#include "V8NodeFilter.h" -#include "V8Window.h" -#include "V8WorkerGlobalScope.h" -#include "V8XPathNSResolver.h" +#include "bindings/core/v8/V8Element.h" +#include "bindings/core/v8/V8NodeFilter.h" +#include "bindings/core/v8/V8Window.h" +#include "bindings/core/v8/V8WorkerGlobalScope.h" +#include "bindings/core/v8/V8XPathNSResolver.h" #include "bindings/v8/ScriptController.h" +#include "bindings/v8/V8AbstractEventListener.h" +#include "bindings/v8/V8BindingMacros.h" #include "bindings/v8/V8NodeFilterCondition.h" #include "bindings/v8/V8ObjectConstructor.h" #include "bindings/v8/V8WindowShell.h" @@ -45,14 +47,16 @@ #include "core/dom/Element.h" #include "core/dom/NodeFilter.h" #include "core/dom/QualifiedName.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" #include "core/inspector/BindingVisitors.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" -#include "core/frame/Settings.h" #include "core/workers/WorkerGlobalScope.h" #include "core/xml/XPathNSResolver.h" -#include "gin/public/isolate_holder.h" +#include "platform/EventTracer.h" +#include "platform/JSONValues.h" #include "wtf/ArrayBufferContents.h" #include "wtf/MainThread.h" #include "wtf/MathExtras.h" @@ -63,38 +67,56 @@ #include "wtf/text/StringBuffer.h" #include "wtf/text/StringHash.h" #include "wtf/text/WTFString.h" +#include "wtf/unicode/CharacterNames.h" +#include "wtf/unicode/Unicode.h" namespace WebCore { -v8::Handle<v8::Value> setDOMException(int exceptionCode, v8::Isolate* isolate) +v8::Handle<v8::Value> throwError(V8ErrorType errorType, const String& message, v8::Isolate* isolate) { - // FIXME: pass in an ExceptionState instead for better creationContext. - return V8ThrowException::throwDOMException(exceptionCode, v8::Handle<v8::Object>(), isolate); + return V8ThrowException::throwError(errorType, message, isolate); } -v8::Handle<v8::Value> setDOMException(int exceptionCode, const String& message, v8::Isolate* isolate) +v8::Handle<v8::Value> throwError(v8::Handle<v8::Value> exception, v8::Isolate* isolate) { - return V8ThrowException::throwDOMException(exceptionCode, message, v8::Handle<v8::Object>(), isolate); + return V8ThrowException::throwError(exception, isolate); } -v8::Handle<v8::Value> throwError(V8ErrorType errorType, const String& message, v8::Isolate* isolate) +v8::Handle<v8::Value> throwTypeError(const String& message, v8::Isolate* isolate) { - return V8ThrowException::throwError(errorType, message, isolate); + return V8ThrowException::throwTypeError(message, isolate); } -v8::Handle<v8::Value> throwError(v8::Handle<v8::Value> exception, v8::Isolate* isolate) +void throwArityTypeErrorForMethod(const char* method, const char* type, const char* valid, unsigned provided, v8::Isolate* isolate) { - return V8ThrowException::throwError(exception, isolate); + throwTypeError(ExceptionMessages::failedToExecute(method, type, ExceptionMessages::invalidArity(valid, provided)), isolate); } -v8::Handle<v8::Value> throwUninformativeAndGenericTypeError(v8::Isolate* isolate) +void throwArityTypeErrorForConstructor(const char* type, const char* valid, unsigned provided, v8::Isolate* isolate) { - return V8ThrowException::throwTypeError(String(), isolate); + throwTypeError(ExceptionMessages::failedToConstruct(type, ExceptionMessages::invalidArity(valid, provided)), isolate); } -v8::Handle<v8::Value> throwTypeError(const String& message, v8::Isolate* isolate) +void throwArityTypeError(ExceptionState& exceptionState, const char* valid, unsigned provided) { - return V8ThrowException::throwTypeError(message, isolate); + exceptionState.throwTypeError(ExceptionMessages::invalidArity(valid, provided)); + exceptionState.throwIfNeeded(); +} + +void throwMinimumArityTypeErrorForMethod(const char* method, const char* type, unsigned expected, unsigned providedLeastNumMandatoryParams, v8::Isolate* isolate) +{ + throwTypeError(ExceptionMessages::failedToExecute(method, type, ExceptionMessages::notEnoughArguments(expected, providedLeastNumMandatoryParams)), isolate); +} + +void throwMinimumArityTypeErrorForConstructor(const char* type, unsigned expected, unsigned providedLeastNumMandatoryParams, v8::Isolate* isolate) +{ + throwTypeError(ExceptionMessages::failedToConstruct(type, ExceptionMessages::notEnoughArguments(expected, providedLeastNumMandatoryParams)), isolate); +} + +void throwMinimumArityTypeError(ExceptionState& exceptionState, unsigned expected, unsigned providedLeastNumMandatoryParams) +{ + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(expected, providedLeastNumMandatoryParams)); + exceptionState.throwIfNeeded(); } class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { @@ -124,14 +146,13 @@ v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator() return &arrayBufferAllocator; } -PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback, v8::Handle<v8::Object> creationContext, ScriptState* scriptState) { - RefPtr<NodeFilter> filter = NodeFilter::create(); + RefPtrWillBeRawPtr<NodeFilter> filter = NodeFilter::create(); - // FIXME: Should pass in appropriate creationContext - v8::Handle<v8::Object> filterWrapper = toV8(filter, v8::Handle<v8::Object>(), isolate).As<v8::Object>(); + v8::Handle<v8::Object> filterWrapper = toV8(filter, creationContext, scriptState->isolate()).As<v8::Object>(); - RefPtr<NodeFilterCondition> condition = V8NodeFilterCondition::create(callback, filterWrapper, isolate); + RefPtrWillBeRawPtr<NodeFilterCondition> condition = V8NodeFilterCondition::create(callback, filterWrapper, scriptState); filter->setCondition(condition.release()); return filter.release(); @@ -140,17 +161,17 @@ PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback, v8::Isolate* const int32_t kMaxInt32 = 0x7fffffff; const int32_t kMinInt32 = -kMaxInt32 - 1; const uint32_t kMaxUInt32 = 0xffffffff; -const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, maximum integer exactly representable in ECMAScript. +const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, maximum uniquely representable integer in ECMAScript. -static double enforceRange(double x, double minimum, double maximum, bool& ok) +static double enforceRange(double x, double minimum, double maximum, const char* typeName, ExceptionState& exceptionState) { if (std::isnan(x) || std::isinf(x)) { - ok = false; + exceptionState.throwTypeError("Value is" + String(std::isinf(x) ? " infinite and" : "") + " not of type '" + String(typeName) + "'."); return 0; } x = trunc(x); if (x < minimum || x > maximum) { - ok = false; + exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range."); return 0; } return x; @@ -187,10 +208,9 @@ struct IntTypeLimits<uint16_t> { }; template <typename T> -static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, const char* typeName, ExceptionState& exceptionState) { typedef IntTypeLimits<T> LimitsTrait; - ok = true; // Fast case. The value is already a 32-bit integer in the right range. if (value->IsInt32()) { @@ -198,7 +218,7 @@ static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfi if (result >= LimitsTrait::minValue && result <= LimitsTrait::maxValue) return static_cast<T>(result); if (configuration == EnforceRange) { - ok = false; + exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range."); return 0; } result %= LimitsTrait::numberOfValues; @@ -206,14 +226,14 @@ static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfi } // Can the value be converted to a number? - v8::Local<v8::Number> numberObject = value->ToNumber(); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { - ok = false; + exceptionState.throwTypeError("Not convertible to a number value (of type '" + String(typeName) + "'."); return 0; } if (configuration == EnforceRange) - return enforceRange(numberObject->Value(), LimitsTrait::minValue, LimitsTrait::maxValue, ok); + return enforceRange(numberObject->Value(), LimitsTrait::minValue, LimitsTrait::maxValue, typeName, exceptionState); double numberValue = numberObject->Value(); if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue) @@ -226,10 +246,9 @@ static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfi } template <typename T> -static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, const char* typeName, ExceptionState& exceptionState) { typedef IntTypeLimits<T> LimitsTrait; - ok = true; // Fast case. The value is a 32-bit signed integer - possibly positive? if (value->IsInt32()) { @@ -237,21 +256,21 @@ static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConf if (result >= 0 && result <= LimitsTrait::maxValue) return static_cast<T>(result); if (configuration == EnforceRange) { - ok = false; + exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range."); return 0; } return static_cast<T>(result); } // Can the value be converted to a number? - v8::Local<v8::Number> numberObject = value->ToNumber(); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { - ok = false; + exceptionState.throwTypeError("Not convertible to a number value (of type '" + String(typeName) + "'."); return 0; } if (configuration == EnforceRange) - return enforceRange(numberObject->Value(), 0, LimitsTrait::maxValue, ok); + return enforceRange(numberObject->Value(), 0, LimitsTrait::maxValue, typeName, exceptionState); // Does the value convert to nan or to an infinity? double numberValue = numberObject->Value(); @@ -265,44 +284,65 @@ static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConf return static_cast<T>(fmod(numberValue, LimitsTrait::numberOfValues)); } -int8_t toInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +int8_t toInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) +{ + return toSmallerInt<int8_t>(value, configuration, "byte", exceptionState); +} + +int8_t toInt8(v8::Handle<v8::Value> value) +{ + NonThrowableExceptionState exceptionState; + return toInt8(value, NormalConversion, exceptionState); +} + +uint8_t toUInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toSmallerInt<int8_t>(value, configuration, ok); + return toSmallerUInt<uint8_t>(value, configuration, "octet", exceptionState); } -uint8_t toUInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +uint8_t toUInt8(v8::Handle<v8::Value> value) { - return toSmallerUInt<uint8_t>(value, configuration, ok); + NonThrowableExceptionState exceptionState; + return toUInt8(value, NormalConversion, exceptionState); } -int16_t toInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +int16_t toInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toSmallerInt<int16_t>(value, configuration, ok); + return toSmallerInt<int16_t>(value, configuration, "short", exceptionState); } -uint16_t toUInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +int16_t toInt16(v8::Handle<v8::Value> value) { - return toSmallerUInt<uint16_t>(value, configuration, ok); + NonThrowableExceptionState exceptionState; + return toInt16(value, NormalConversion, exceptionState); } -int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +uint16_t toUInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - ok = true; + return toSmallerUInt<uint16_t>(value, configuration, "unsigned short", exceptionState); +} +uint16_t toUInt16(v8::Handle<v8::Value> value) +{ + NonThrowableExceptionState exceptionState; + return toUInt16(value, NormalConversion, exceptionState); +} + +int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) +{ // Fast case. The value is already a 32-bit integer. if (value->IsInt32()) return value->Int32Value(); // Can the value be converted to a number? - ok = false; - V8TRYCATCH_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), 0); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { + exceptionState.throwTypeError("Not convertible to a number value (of type 'long'.)"); return 0; } - ok = true; if (configuration == EnforceRange) - return enforceRange(numberObject->Value(), kMinInt32, kMaxInt32, ok); + return enforceRange(numberObject->Value(), kMinInt32, kMaxInt32, "long", exceptionState); // Does the value convert to nan or to an infinity? double numberValue = numberObject->Value(); @@ -312,14 +352,18 @@ int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf if (configuration == Clamp) return clampTo<int32_t>(numberObject->Value()); - V8TRYCATCH_RETURN(int32_t, result, numberObject->Int32Value(), 0); + TONATIVE_DEFAULT_EXCEPTIONSTATE(int32_t, result, numberObject->Int32Value(), exceptionState, 0); return result; } -uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +int32_t toInt32(v8::Handle<v8::Value> value) { - ok = true; + NonThrowableExceptionState exceptionState; + return toInt32(value, NormalConversion, exceptionState); +} +uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) +{ // Fast case. The value is already a 32-bit unsigned integer. if (value->IsUint32()) return value->Uint32Value(); @@ -330,22 +374,21 @@ uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration co if (result >= 0) return result; if (configuration == EnforceRange) { - ok = false; + exceptionState.throwTypeError("Value is outside the 'unsigned long' value range."); return 0; } return result; } // Can the value be converted to a number? - ok = false; - V8TRYCATCH_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), 0); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { + exceptionState.throwTypeError("Not convertible to a number value (of type 'unsigned long'.)"); return 0; } - ok = true; if (configuration == EnforceRange) - return enforceRange(numberObject->Value(), 0, kMaxUInt32, ok); + return enforceRange(numberObject->Value(), 0, kMaxUInt32, "unsigned long", exceptionState); // Does the value convert to nan or to an infinity? double numberValue = numberObject->Value(); @@ -355,29 +398,33 @@ uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration co if (configuration == Clamp) return clampTo<uint32_t>(numberObject->Value()); - V8TRYCATCH_RETURN(uint32_t, result, numberObject->Uint32Value(), 0); + TONATIVE_DEFAULT(uint32_t, result, numberObject->Uint32Value(), 0); return result; } -int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +uint32_t toUInt32(v8::Handle<v8::Value> value) { - ok = true; + NonThrowableExceptionState exceptionState; + return toUInt32(value, NormalConversion, exceptionState); +} +int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) +{ // Fast case. The value is a 32-bit integer. if (value->IsInt32()) return value->Int32Value(); // Can the value be converted to a number? - v8::Local<v8::Number> numberObject = value->ToNumber(); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { - ok = false; + exceptionState.throwTypeError("Not convertible to a number value (of type 'long long'.)"); return 0; } double x = numberObject->Value(); if (configuration == EnforceRange) - return enforceRange(x, -kJSMaxInteger, kJSMaxInteger, ok); + return enforceRange(x, -kJSMaxInteger, kJSMaxInteger, "long long", exceptionState); // Does the value convert to nan or to an infinity? if (std::isnan(x) || std::isinf(x)) @@ -389,10 +436,14 @@ int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf return integer; } -uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +int64_t toInt64(v8::Handle<v8::Value> value) { - ok = true; + NonThrowableExceptionState exceptionState; + return toInt64(value, NormalConversion, exceptionState); +} +uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) +{ // Fast case. The value is a 32-bit unsigned integer. if (value->IsUint32()) return value->Uint32Value(); @@ -403,23 +454,23 @@ uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration co if (result >= 0) return result; if (configuration == EnforceRange) { - ok = false; + exceptionState.throwTypeError("Value is outside the 'unsigned long long' value range."); return 0; } return result; } // Can the value be converted to a number? - v8::Local<v8::Number> numberObject = value->ToNumber(); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { - ok = false; + exceptionState.throwTypeError("Not convertible to a number value (of type 'unsigned long long'.)"); return 0; } double x = numberObject->Value(); if (configuration == EnforceRange) - return enforceRange(x, 0, kJSMaxInteger, ok); + return enforceRange(x, 0, kJSMaxInteger, "unsigned long long", exceptionState); // Does the value convert to nan or to an infinity? if (std::isnan(x) || std::isinf(x)) @@ -431,134 +482,283 @@ uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration co return integer; } -v8::Handle<v8::FunctionTemplate> createRawTemplate(v8::Isolate* isolate) +uint64_t toUInt64(v8::Handle<v8::Value> value) +{ + NonThrowableExceptionState exceptionState; + return toUInt64(value, NormalConversion, exceptionState); +} + +float toFloat(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); + return numberObject->NumberValue(); +} + +String toByteString(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + // Handle null default value. + if (value.IsEmpty()) + return String(); + + // From the Web IDL spec: http://heycam.github.io/webidl/#es-ByteString + if (value.IsEmpty()) + return String(); + + // 1. Let x be ToString(v) + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::String>, stringObject, value->ToString(), exceptionState, String()); + String x = toCoreString(stringObject); + + // 2. If the value of any element of x is greater than 255, then throw a TypeError. + if (!x.containsOnlyLatin1()) { + exceptionState.throwTypeError("Value is not a valid ByteString."); + return String(); + } + + // 3. Return an IDL ByteString value whose length is the length of x, and where the + // value of each element is the value of the corresponding element of x. + // Blink: A ByteString is simply a String with a range constrained per the above, so + // this is the identity operation. + return x; +} + +static bool hasUnmatchedSurrogates(const String& string) +{ + // By definition, 8-bit strings are confined to the Latin-1 code page and + // have no surrogates, matched or otherwise. + if (string.is8Bit()) + return false; + + const UChar* characters = string.characters16(); + const unsigned length = string.length(); + + for (unsigned i = 0; i < length; ++i) { + UChar c = characters[i]; + if (U16_IS_SINGLE(c)) + continue; + if (U16_IS_TRAIL(c)) + return true; + ASSERT(U16_IS_LEAD(c)); + if (i == length - 1) + return true; + UChar d = characters[i + 1]; + if (!U16_IS_TRAIL(d)) + return true; + ++i; + } + return false; +} + +// Replace unmatched surrogates with REPLACEMENT CHARACTER U+FFFD. +static String replaceUnmatchedSurrogates(const String& string) +{ + // This roughly implements http://heycam.github.io/webidl/#dfn-obtain-unicode + // but since Blink strings are 16-bits internally, the output is simply + // re-encoded to UTF-16. + + // The concept of surrogate pairs is explained at: + // http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G2630 + + // Blink-specific optimization to avoid making an unnecessary copy. + if (!hasUnmatchedSurrogates(string)) + return string; + ASSERT(!string.is8Bit()); + + // 1. Let S be the DOMString value. + const UChar* s = string.characters16(); + + // 2. Let n be the length of S. + const unsigned n = string.length(); + + // 3. Initialize i to 0. + unsigned i = 0; + + // 4. Initialize U to be an empty sequence of Unicode characters. + StringBuilder u; + u.reserveCapacity(n); + + // 5. While i < n: + while (i < n) { + // 1. Let c be the code unit in S at index i. + UChar c = s[i]; + // 2. Depending on the value of c: + if (U16_IS_SINGLE(c)) { + // c < 0xD800 or c > 0xDFFF + // Append to U the Unicode character with code point c. + u.append(c); + } else if (U16_IS_TRAIL(c)) { + // 0xDC00 <= c <= 0xDFFF + // Append to U a U+FFFD REPLACEMENT CHARACTER. + u.append(WTF::Unicode::replacementCharacter); + } else { + // 0xD800 <= c <= 0xDBFF + ASSERT(U16_IS_LEAD(c)); + if (i == n - 1) { + // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT CHARACTER. + u.append(WTF::Unicode::replacementCharacter); + } else { + // 2. Otherwise, i < n−1: + ASSERT(i < n - 1); + // ....1. Let d be the code unit in S at index i+1. + UChar d = s[i + 1]; + if (U16_IS_TRAIL(d)) { + // 2. If 0xDC00 <= d <= 0xDFFF, then: + // ..1. Let a be c & 0x3FF. + // ..2. Let b be d & 0x3FF. + // ..3. Append to U the Unicode character with code point 2^16+2^10*a+b. + u.append(U16_GET_SUPPLEMENTARY(c, d)); + // Blink: This is equivalent to u.append(c); u.append(d); + ++i; + } else { + // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a U+FFFD REPLACEMENT CHARACTER. + u.append(WTF::Unicode::replacementCharacter); + } + } + } + // 3. Set i to i+1. + ++i; + } + + // 6. Return U. + ASSERT(u.length() == string.length()); + return u.toString(); +} + +String toScalarValueString(v8::Handle<v8::Value> value, ExceptionState& exceptionState) { - v8::EscapableHandleScope scope(isolate); - v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(isolate, V8ObjectConstructor::isValidConstructorMode); - return scope.Escape(result); + // From the Encoding standard (with a TODO to move to Web IDL): + // http://encoding.spec.whatwg.org/#type-scalarvaluestring + if (value.IsEmpty()) + return String(); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::String>, stringObject, value->ToString(), exceptionState, String()); + + // ScalarValueString is identical to DOMString except that "convert a + // DOMString to a sequence of Unicode characters" is used subsequently + // when converting to an IDL value + String x = toCoreString(stringObject); + return replaceUnmatchedSurrogates(x); } -PassRefPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value> value, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value> value, v8::Isolate* isolate) { - RefPtr<XPathNSResolver> resolver; - if (V8XPathNSResolver::hasInstance(value, isolate, worldType(isolate))) + RefPtrWillBeRawPtr<XPathNSResolver> resolver = nullptr; + if (V8XPathNSResolver::hasInstance(value, isolate)) resolver = V8XPathNSResolver::toNative(v8::Handle<v8::Object>::Cast(value)); else if (value->IsObject()) resolver = V8CustomXPathNSResolver::create(value->ToObject(), isolate); return resolver; } -v8::Handle<v8::Object> toInnerGlobalObject(v8::Handle<v8::Context> context) +LocalDOMWindow* toDOMWindow(v8::Handle<v8::Value> value, v8::Isolate* isolate) { - return v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); + if (value.IsEmpty() || !value->IsObject()) + return 0; + + v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(v8::Handle<v8::Object>::Cast(value), isolate); + if (!windowWrapper.IsEmpty()) + return V8Window::toNative(windowWrapper); + return 0; } -DOMWindow* toDOMWindow(v8::Handle<v8::Context> context) +LocalDOMWindow* toDOMWindow(v8::Handle<v8::Context> context) { - v8::Handle<v8::Object> global = context->Global(); - ASSERT(!global.IsEmpty()); - v8::Handle<v8::Object> window = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), MainWorld)); - if (!window.IsEmpty()) - return V8Window::toNative(window); - window = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), IsolatedWorld)); - ASSERT(!window.IsEmpty()); - return V8Window::toNative(window); + if (context.IsEmpty()) + return 0; + return toDOMWindow(context->Global(), context->GetIsolate()); +} + +LocalDOMWindow* enteredDOMWindow(v8::Isolate* isolate) +{ + LocalDOMWindow* window = toDOMWindow(isolate->GetEnteredContext()); + if (!window) { + // We don't always have an entered DOM window, for example during microtask callbacks from V8 + // (where the entered context may be the DOM-in-JS context). In that case, we fall back + // to the current context. + window = currentDOMWindow(isolate); + ASSERT(window); + } + return window; +} + +LocalDOMWindow* currentDOMWindow(v8::Isolate* isolate) +{ + return toDOMWindow(isolate->GetCurrentContext()); +} + +LocalDOMWindow* callingDOMWindow(v8::Isolate* isolate) +{ + v8::Handle<v8::Context> context = isolate->GetCallingContext(); + if (context.IsEmpty()) { + // Unfortunately, when processing script from a plug-in, we might not + // have a calling context. In those cases, we fall back to the + // entered context. + context = isolate->GetEnteredContext(); + } + return toDOMWindow(context); } ExecutionContext* toExecutionContext(v8::Handle<v8::Context> context) { v8::Handle<v8::Object> global = context->Global(); - v8::Handle<v8::Object> windowWrapper = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), MainWorld)); - if (!windowWrapper.IsEmpty()) - return V8Window::toNative(windowWrapper)->executionContext(); - windowWrapper = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), IsolatedWorld)); + v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(global, context->GetIsolate()); if (!windowWrapper.IsEmpty()) return V8Window::toNative(windowWrapper)->executionContext(); - v8::Handle<v8::Object> workerWrapper = global->FindInstanceInPrototypeChain(V8WorkerGlobalScope::domTemplate(context->GetIsolate(), WorkerWorld)); + v8::Handle<v8::Object> workerWrapper = V8WorkerGlobalScope::findInstanceInPrototypeChain(global, context->GetIsolate()); if (!workerWrapper.IsEmpty()) return V8WorkerGlobalScope::toNative(workerWrapper)->executionContext(); // FIXME: Is this line of code reachable? return 0; } -DOMWindow* activeDOMWindow() +ExecutionContext* currentExecutionContext(v8::Isolate* isolate) { - v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCallingContext(); - if (context.IsEmpty()) { - // Unfortunately, when processing script from a plug-in, we might not - // have a calling context. In those cases, we fall back to the - // entered context. - context = v8::Isolate::GetCurrent()->GetEnteredContext(); - } - return toDOMWindow(context); + return toExecutionContext(isolate->GetCurrentContext()); } -ExecutionContext* activeExecutionContext() +ExecutionContext* callingExecutionContext(v8::Isolate* isolate) { - v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCallingContext(); + v8::Handle<v8::Context> context = isolate->GetCallingContext(); if (context.IsEmpty()) { // Unfortunately, when processing script from a plug-in, we might not // have a calling context. In those cases, we fall back to the // entered context. - context = v8::Isolate::GetCurrent()->GetEnteredContext(); + context = isolate->GetEnteredContext(); } return toExecutionContext(context); } -DOMWindow* firstDOMWindow() -{ - return toDOMWindow(v8::Isolate::GetCurrent()->GetEnteredContext()); -} - -Document* currentDocument() -{ - return toDOMWindow(v8::Isolate::GetCurrent()->GetCurrentContext())->document(); -} - -Frame* toFrameIfNotDetached(v8::Handle<v8::Context> context) +LocalFrame* toFrameIfNotDetached(v8::Handle<v8::Context> context) { - DOMWindow* window = toDOMWindow(context); - if (window->isCurrentlyDisplayedInFrame()) + LocalDOMWindow* window = toDOMWindow(context); + if (window && window->isCurrentlyDisplayedInFrame()) return window->frame(); - // We return 0 here because |context| is detached from the Frame. If we + // We return 0 here because |context| is detached from the LocalFrame. If we // did return |frame| we could get in trouble because the frame could be // navigated to another security origin. return 0; } -v8::Local<v8::Context> toV8Context(ExecutionContext* context, DOMWrapperWorld* world) +v8::Local<v8::Context> toV8Context(ExecutionContext* context, DOMWrapperWorld& world) { + ASSERT(context); if (context->isDocument()) { - ASSERT(world); - if (Frame* frame = toDocument(context)->frame()) + if (LocalFrame* frame = toDocument(context)->frame()) return frame->script().windowShell(world)->context(); } else if (context->isWorkerGlobalScope()) { - ASSERT(!world); if (WorkerScriptController* script = toWorkerGlobalScope(context)->script()) return script->context(); } return v8::Local<v8::Context>(); } -bool handleOutOfMemory() +v8::Local<v8::Context> toV8Context(LocalFrame* frame, DOMWrapperWorld& world) { - v8::Local<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext(); - - if (!context->HasOutOfMemoryException()) - return false; - - // Warning, error, disable JS for this frame? - Frame* frame = toFrameIfNotDetached(context); if (!frame) - return true; - - frame->script().clearForOutOfMemory(); - frame->loader().client()->didExhaustMemoryAvailableForScript(); - - if (Settings* settings = frame->settings()) - settings->setScriptEnabled(false); - - return true; + return v8::Local<v8::Context>(); + v8::Local<v8::Context> context = frame->script().windowShell(world)->context(); + if (context.IsEmpty()) + return v8::Local<v8::Context>(); + LocalFrame* attachedFrame= toFrameIfNotDetached(context); + return frame == attachedFrame ? context : v8::Local<v8::Context>(); } v8::Local<v8::Value> handleMaxRecursionDepthExceeded(v8::Isolate* isolate) @@ -576,73 +776,165 @@ void crashIfV8IsDead() } } -WrapperWorldType worldType(v8::Isolate* isolate) +v8::Handle<v8::Function> getBoundFunction(v8::Handle<v8::Function> function) { - V8PerIsolateData* data = V8PerIsolateData::from(isolate); - if (!data->workerDOMDataStore()) - return worldTypeInMainThread(isolate); - return WorkerWorld; + v8::Handle<v8::Value> boundFunction = function->GetBoundFunction(); + return boundFunction->IsFunction() ? v8::Handle<v8::Function>::Cast(boundFunction) : function; } -WrapperWorldType worldTypeInMainThread(v8::Isolate* isolate) +void addHiddenValueToArray(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int arrayIndex, v8::Isolate* isolate) { - if (!DOMWrapperWorld::isolatedWorldsExist()) - return MainWorld; - ASSERT(!isolate->GetEnteredContext().IsEmpty()); - DOMWrapperWorld* isolatedWorld = DOMWrapperWorld::isolatedWorld(isolate->GetEnteredContext()); - if (isolatedWorld) - return IsolatedWorld; - return MainWorld; + v8::Local<v8::Value> arrayValue = object->GetInternalField(arrayIndex); + if (arrayValue->IsNull() || arrayValue->IsUndefined()) { + arrayValue = v8::Array::New(isolate); + object->SetInternalField(arrayIndex, arrayValue); + } + + v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(arrayValue); + array->Set(v8::Integer::New(isolate, array->Length()), value); } -DOMWrapperWorld* isolatedWorldForIsolate(v8::Isolate* isolate) +void removeHiddenValueFromArray(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int arrayIndex, v8::Isolate* isolate) { - V8PerIsolateData* data = V8PerIsolateData::from(isolate); - if (data->workerDOMDataStore()) - return 0; - if (!DOMWrapperWorld::isolatedWorldsExist()) - return 0; - ASSERT(isolate->InContext()); - return DOMWrapperWorld::isolatedWorld(isolate->GetCurrentContext()); + v8::Local<v8::Value> arrayValue = object->GetInternalField(arrayIndex); + if (!arrayValue->IsArray()) + return; + v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(arrayValue); + for (int i = array->Length() - 1; i >= 0; --i) { + v8::Local<v8::Value> item = array->Get(v8::Integer::New(isolate, i)); + if (item->StrictEquals(value)) { + array->Delete(i); + return; + } + } } -v8::Local<v8::Value> getHiddenValueFromMainWorldWrapper(v8::Isolate* isolate, ScriptWrappable* wrappable, v8::Handle<v8::String> key) +void moveEventListenerToNewWrapper(v8::Handle<v8::Object> object, EventListener* oldValue, v8::Local<v8::Value> newValue, int arrayIndex, v8::Isolate* isolate) { - v8::Local<v8::Object> wrapper = wrappable->newLocalWrapper(isolate); - return wrapper.IsEmpty() ? v8::Local<v8::Value>() : wrapper->GetHiddenValue(key); + if (oldValue) { + V8AbstractEventListener* oldListener = V8AbstractEventListener::cast(oldValue); + if (oldListener) { + v8::Local<v8::Object> oldListenerObject = oldListener->getExistingListenerObject(); + if (!oldListenerObject.IsEmpty()) + removeHiddenValueFromArray(object, oldListenerObject, arrayIndex, isolate); + } + } + // Non-callable input is treated as null and ignored + if (newValue->IsFunction()) + addHiddenValueToArray(object, newValue, arrayIndex, isolate); } -static gin::IsolateHolder* mainIsolateHolder = 0; +v8::Isolate* toIsolate(ExecutionContext* context) +{ + if (context && context->isDocument()) + return V8PerIsolateData::mainThreadIsolate(); + return v8::Isolate::GetCurrent(); +} -v8::Isolate* mainThreadIsolate() +v8::Isolate* toIsolate(LocalFrame* frame) { - ASSERT(mainIsolateHolder); - ASSERT(isMainThread()); - return mainIsolateHolder->isolate(); + ASSERT(frame); + return frame->script().isolate(); } -void setMainThreadIsolate(v8::Isolate* isolate) +PassRefPtr<JSONValue> v8ToJSONValue(v8::Isolate* isolate, v8::Handle<v8::Value> value, int maxDepth) { - ASSERT(!mainIsolateHolder || !isolate); - ASSERT(isMainThread()); - if (isolate) { - mainIsolateHolder = new gin::IsolateHolder(isolate); - } else { - delete mainIsolateHolder; - mainIsolateHolder = 0; + if (value.IsEmpty()) { + ASSERT_NOT_REACHED(); + return nullptr; + } + + if (!maxDepth) + return nullptr; + maxDepth--; + + if (value->IsNull() || value->IsUndefined()) + return JSONValue::null(); + if (value->IsBoolean()) + return JSONBasicValue::create(value->BooleanValue()); + if (value->IsNumber()) + return JSONBasicValue::create(value->NumberValue()); + if (value->IsString()) + return JSONString::create(toCoreString(value.As<v8::String>())); + if (value->IsArray()) { + v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); + RefPtr<JSONArray> inspectorArray = JSONArray::create(); + uint32_t length = array->Length(); + for (uint32_t i = 0; i < length; i++) { + v8::Local<v8::Value> value = array->Get(v8::Int32::New(isolate, i)); + RefPtr<JSONValue> element = v8ToJSONValue(isolate, value, maxDepth); + if (!element) + return nullptr; + inspectorArray->pushValue(element); + } + return inspectorArray; + } + if (value->IsObject()) { + RefPtr<JSONObject> jsonObject = JSONObject::create(); + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); + v8::Local<v8::Array> propertyNames = object->GetPropertyNames(); + uint32_t length = propertyNames->Length(); + for (uint32_t i = 0; i < length; i++) { + v8::Local<v8::Value> name = propertyNames->Get(v8::Int32::New(isolate, i)); + // FIXME(yurys): v8::Object should support GetOwnPropertyNames + if (name->IsString() && !object->HasRealNamedProperty(v8::Handle<v8::String>::Cast(name))) + continue; + RefPtr<JSONValue> propertyValue = v8ToJSONValue(isolate, object->Get(name), maxDepth); + if (!propertyValue) + return nullptr; + TOSTRING_DEFAULT(V8StringResource<WithNullCheck>, nameString, name, nullptr); + jsonObject->setValue(nameString, propertyValue); + } + return jsonObject; } + ASSERT_NOT_REACHED(); + return nullptr; } -v8::Isolate* toIsolate(ExecutionContext* context) +V8TestingScope::V8TestingScope(v8::Isolate* isolate) + : m_handleScope(isolate) + , m_contextScope(v8::Context::New(isolate)) + , m_scriptState(ScriptStateForTesting::create(isolate->GetCurrentContext(), DOMWrapperWorld::create())) { - if (context && context->isDocument()) - return mainThreadIsolate(); - return v8::Isolate::GetCurrent(); } -v8::Isolate* toIsolate(Frame* frame) +V8TestingScope::~V8TestingScope() { - return frame->script().isolate(); + m_scriptState->disposePerContextData(); +} + +ScriptState* V8TestingScope::scriptState() const +{ + return m_scriptState.get(); +} + +v8::Isolate* V8TestingScope::isolate() const +{ + return m_scriptState->isolate(); +} + +void GetDevToolsFunctionInfo(v8::Handle<v8::Function> function, v8::Isolate* isolate, int& scriptId, String& resourceName, int& lineNumber) +{ + v8::Handle<v8::Function> originalFunction = getBoundFunction(function); + scriptId = originalFunction->ScriptId(); + v8::ScriptOrigin origin = originalFunction->GetScriptOrigin(); + if (!origin.ResourceName().IsEmpty()) { + resourceName = NativeValueTraits<String>::nativeValue(origin.ResourceName(), isolate); + lineNumber = originalFunction->GetScriptLineNumber() + 1; + } + if (resourceName.isEmpty()) { + resourceName = "undefined"; + lineNumber = 1; + } +} + +PassRefPtr<TraceEvent::ConvertableToTraceFormat> devToolsTraceEventData(ExecutionContext* context, v8::Handle<v8::Function> function, v8::Isolate* isolate) +{ + int scriptId = 0; + String resourceName; + int lineNumber = 1; + GetDevToolsFunctionInfo(function, isolate, scriptId, resourceName, lineNumber); + return InspectorFunctionCallEvent::data(context, scriptId, resourceName, lineNumber); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.h b/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.h index 48200a2fdd0..7fb8e727b57 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.h @@ -34,668 +34,942 @@ #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ExceptionMessages.h" +#include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8BindingMacros.h" #include "bindings/v8/V8PerIsolateData.h" #include "bindings/v8/V8StringResource.h" #include "bindings/v8/V8ThrowException.h" #include "bindings/v8/V8ValueCache.h" +#include "platform/heap/Heap.h" #include "wtf/MathExtras.h" #include "wtf/text/AtomicString.h" #include <v8.h> namespace WebCore { - class DOMWindow; - class Document; - class Frame; - class NodeFilter; - class ExecutionContext; - class ScriptWrappable; - class XPathNSResolver; +class LocalDOMWindow; +class Document; +class EventListener; +class ExecutionContext; +class ExceptionState; +class LocalFrame; +class NodeFilter; +class ScriptWrappable; +class XPathNSResolver; + +namespace TraceEvent { +class ConvertableToTraceFormat; +} + +const int kMaxRecursionDepth = 22; + +// Schedule a JavaScript error to be thrown. +v8::Handle<v8::Value> throwError(V8ErrorType, const String&, v8::Isolate*); + +// Schedule a JavaScript error to be thrown. +v8::Handle<v8::Value> throwError(v8::Handle<v8::Value>, v8::Isolate*); + +// A helper for throwing JavaScript TypeError. +v8::Handle<v8::Value> throwTypeError(const String&, v8::Isolate*); + +// Helpers for throwing JavaScript TypeErrors for arity mismatches. +void throwArityTypeErrorForMethod(const char* method, const char* type, const char* valid, unsigned provided, v8::Isolate*); +void throwArityTypeErrorForConstructor(const char* type, const char* valid, unsigned provided, v8::Isolate*); +void throwArityTypeError(ExceptionState&, const char* valid, unsigned provided); +void throwMinimumArityTypeErrorForMethod(const char* method, const char* type, unsigned expected, unsigned providedLeastNumMandatoryParams, v8::Isolate*); +void throwMinimumArityTypeErrorForConstructor(const char* type, unsigned expected, unsigned providedLeastNumMandatoryParams, v8::Isolate*); +void throwMinimumArityTypeError(ExceptionState&, unsigned expected, unsigned providedLeastNumMandatoryParams); + +v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator(); + +inline v8::Handle<v8::Value> argumentOrNull(const v8::FunctionCallbackInfo<v8::Value>& info, int index) +{ + return index >= info.Length() ? v8::Local<v8::Value>() : info[index]; +} + +template<typename CallbackInfo, typename V> +inline void v8SetReturnValue(const CallbackInfo& info, V v) +{ + info.GetReturnValue().Set(v); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueBool(const CallbackInfo& info, bool v) +{ + info.GetReturnValue().Set(v); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueInt(const CallbackInfo& info, int v) +{ + info.GetReturnValue().Set(v); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueUnsigned(const CallbackInfo& info, unsigned v) +{ + info.GetReturnValue().Set(v); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueNull(const CallbackInfo& info) +{ + info.GetReturnValue().SetNull(); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueUndefined(const CallbackInfo& info) +{ + info.GetReturnValue().SetUndefined(); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueEmptyString(const CallbackInfo& info) +{ + info.GetReturnValue().SetEmptyString(); +} + +template <class CallbackInfo> +inline void v8SetReturnValueString(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +{ + if (string.isNull()) { + v8SetReturnValueEmptyString(info); + return; + } + V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); +} + +template <class CallbackInfo> +inline void v8SetReturnValueStringOrNull(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +{ + if (string.isNull()) { + v8SetReturnValueNull(info); + return; + } + V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); +} + +template <class CallbackInfo> +inline void v8SetReturnValueStringOrUndefined(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +{ + if (string.isNull()) { + v8SetReturnValueUndefined(info); + return; + } + V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); +} + +// Convert v8::String to a WTF::String. If the V8 string is not already +// an external string then it is transformed into an external string at this +// point to avoid repeated conversions. +inline String toCoreString(v8::Handle<v8::String> value) +{ + return v8StringToWebCoreString<String>(value, Externalize); +} + +inline String toCoreStringWithNullCheck(v8::Handle<v8::String> value) +{ + if (value.IsEmpty() || value->IsNull()) + return String(); + return toCoreString(value); +} + +inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::String> value) +{ + if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) + return String(); + return toCoreString(value); +} + +inline AtomicString toCoreAtomicString(v8::Handle<v8::String> value) +{ + return v8StringToWebCoreString<AtomicString>(value, Externalize); +} + +// This method will return a null String if the v8::Value does not contain a v8::String. +// It will not call ToString() on the v8::Value. If you want ToString() to be called, +// please use the TONATIVE_FOR_V8STRINGRESOURCE_*() macros instead. +inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::Value> value) +{ + if (value.IsEmpty() || !value->IsString()) + return String(); + return toCoreString(value.As<v8::String>()); +} + +// Convert a string to a V8 string. +// Return a V8 external string that shares the underlying buffer with the given +// WebCore string. The reference counting mechanism is used to keep the +// underlying buffer alive while the string is still live in the V8 engine. +inline v8::Handle<v8::String> v8String(v8::Isolate* isolate, const String& string) +{ + if (string.isNull()) + return v8::String::Empty(isolate); + return V8PerIsolateData::from(isolate)->stringCache()->v8ExternalString(string.impl(), isolate); +} + +inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str) +{ + ASSERT(isolate); + return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, strlen(str)); +} - const int kMaxRecursionDepth = 22; +inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str, size_t length) +{ + ASSERT(isolate); + return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, length); +} - // Schedule a DOM exception to be thrown, if the exception code is different - // from zero. - v8::Handle<v8::Value> setDOMException(int, v8::Isolate*); - v8::Handle<v8::Value> setDOMException(int, const String&, v8::Isolate*); +inline v8::Handle<v8::Value> v8Undefined() +{ + return v8::Handle<v8::Value>(); +} - // Schedule a JavaScript error to be thrown. - v8::Handle<v8::Value> throwError(V8ErrorType, const String&, v8::Isolate*); - - // Schedule a JavaScript error to be thrown. - v8::Handle<v8::Value> throwError(v8::Handle<v8::Value>, v8::Isolate*); - - // A helper for throwing JavaScript TypeError. - v8::Handle<v8::Value> throwTypeError(const String&, v8::Isolate*); - - // FIXME: Remove this once we kill its callers. - v8::Handle<v8::Value> throwUninformativeAndGenericTypeError(v8::Isolate*); - - v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator(); - - v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value>, uint32_t& length, v8::Isolate*); - - inline v8::Handle<v8::Value> argumentOrNull(const v8::FunctionCallbackInfo<v8::Value>& info, int index) +template <class T> +struct V8ValueTraits { + // FIXME: This function requires the associated generated header to be + // included. Also, this function does not match with other V8ValueTraits + // classes. Remove this V8ValueTraits if possible. + static inline v8::Handle<v8::Value> toV8Value(const T& value, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { - return index >= info.Length() ? v8::Local<v8::Value>() : info[index]; + return toV8(WTF::getPtr(value), creationContext, isolate); } +}; - template<typename CallbackInfo, typename V> - inline void v8SetReturnValue(const CallbackInfo& info, V v) +template<> +struct V8ValueTraits<String> { + static inline v8::Handle<v8::Value> toV8Value(const String& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().Set(v); + return v8String(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueBool(const CallbackInfo& info, bool v) +template<> +struct V8ValueTraits<AtomicString> { + static inline v8::Handle<v8::Value> toV8Value(const AtomicString& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().Set(v); + return v8String(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueInt(const CallbackInfo& info, int v) +template<size_t n> +struct V8ValueTraits<char[n]> { + static inline v8::Handle<v8::Value> toV8Value(char const (&value)[n], v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().Set(v); + return v8String(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueUnsigned(const CallbackInfo& info, unsigned v) +template<> +struct V8ValueTraits<const char*> { + static inline v8::Handle<v8::Value> toV8Value(const char* const& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().Set(v); + return v8String(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueNull(const CallbackInfo& info) +template<> +struct V8ValueTraits<int> { + static inline v8::Handle<v8::Value> toV8Value(const int& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().SetNull(); + return v8::Integer::New(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueUndefined(const CallbackInfo& info) +template<> +struct V8ValueTraits<long> { + static inline v8::Handle<v8::Value> toV8Value(const long& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().SetUndefined(); + return v8::Integer::New(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueEmptyString(const CallbackInfo& info) +template<> +struct V8ValueTraits<unsigned> { + static inline v8::Handle<v8::Value> toV8Value(const unsigned& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().SetEmptyString(); + return v8::Integer::NewFromUnsigned(isolate, value); } +}; - template <class CallbackInfo> - inline void v8SetReturnValueString(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +template<> +struct V8ValueTraits<unsigned long> { + static inline v8::Handle<v8::Value> toV8Value(const unsigned long& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - if (string.isNull()) { - v8SetReturnValueEmptyString(info); - return; - } - V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); + return v8::Integer::NewFromUnsigned(isolate, value); } +}; - template <class CallbackInfo> - inline void v8SetReturnValueStringOrNull(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +template<> +struct V8ValueTraits<float> { + static inline v8::Handle<v8::Value> toV8Value(const float& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - if (string.isNull()) { - v8SetReturnValueNull(info); - return; - } - V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); + return v8::Number::New(isolate, value); } +}; - template <class CallbackInfo> - inline void v8SetReturnValueStringOrUndefined(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +template<> +struct V8ValueTraits<double> { + static inline v8::Handle<v8::Value> toV8Value(const double& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - if (string.isNull()) { - v8SetReturnValueUndefined(info); - return; - } - V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); + return v8::Number::New(isolate, value); } +}; - // Convert v8::String to a WTF::String. If the V8 string is not already - // an external string then it is transformed into an external string at this - // point to avoid repeated conversions. - inline String toCoreString(v8::Handle<v8::String> value) +template<> +struct V8ValueTraits<bool> { + static inline v8::Handle<v8::Value> toV8Value(const bool& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - return v8StringToWebCoreString<String>(value, Externalize); + return v8::Boolean::New(isolate, value); } +}; - inline String toCoreStringWithNullCheck(v8::Handle<v8::String> value) - { - if (value.IsEmpty() || value->IsNull()) - return String(); - return toCoreString(value); - } +// V8NullType and V8UndefinedType are used only for the value conversion. +class V8NullType { }; +class V8UndefinedType { }; - inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::String> value) +template<> +struct V8ValueTraits<V8NullType> { + static inline v8::Handle<v8::Value> toV8Value(const V8NullType&, v8::Handle<v8::Object>, v8::Isolate* isolate) { - if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) - return String(); - return toCoreString(value); + return v8::Null(isolate); } +}; - inline AtomicString toCoreAtomicString(v8::Handle<v8::String> value) +template<> +struct V8ValueTraits<V8UndefinedType> { + static inline v8::Handle<v8::Value> toV8Value(const V8UndefinedType&, v8::Handle<v8::Object>, v8::Isolate* isolate) { - return v8StringToWebCoreString<AtomicString>(value, Externalize); + return v8::Undefined(isolate); } +}; - // This method will return a null String if the v8::Value does not contain a v8::String. - // It will not call ToString() on the v8::Value. If you want ToString() to be called, - // please use the V8TRYCATCH_FOR_V8STRINGRESOURCE_*() macros instead. - inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::Value> value) +template<> +struct V8ValueTraits<ScriptValue> { + static inline v8::Handle<v8::Value> toV8Value(const ScriptValue& value, v8::Handle<v8::Object>, v8::Isolate*) { - if (value.IsEmpty() || !value->IsString()) - return String(); - - return toCoreString(value.As<v8::String>()); + return value.v8Value(); } +}; - // Convert a string to a V8 string. - // Return a V8 external string that shares the underlying buffer with the given - // WebCore string. The reference counting mechanism is used to keep the - // underlying buffer alive while the string is still live in the V8 engine. - inline v8::Handle<v8::String> v8String(v8::Isolate* isolate, const String& string) +template<> +struct V8ValueTraits<v8::Handle<v8::Value> > { + static inline v8::Handle<v8::Value> toV8Value(const v8::Handle<v8::Value>& value, v8::Handle<v8::Object>, v8::Isolate*) { - if (string.isNull()) - return v8::String::Empty(isolate); - return V8PerIsolateData::from(isolate)->stringCache()->v8ExternalString(string.impl(), isolate); + return value; } +}; - inline v8::Handle<v8::Value> v8Undefined() +template<> +struct V8ValueTraits<v8::Local<v8::Value> > { + static inline v8::Handle<v8::Value> toV8Value(const v8::Local<v8::Value>& value, v8::Handle<v8::Object>, v8::Isolate*) { - return v8::Handle<v8::Value>(); + return value; } +}; - template <class T> - struct V8ValueTraits { - static inline v8::Handle<v8::Value> arrayV8Value(const T& value, v8::Isolate* isolate) - { - return toV8(WTF::getPtr(value), v8::Handle<v8::Object>(), isolate); - } - }; - - template<> - struct V8ValueTraits<String> { - static inline v8::Handle<v8::Value> arrayV8Value(const String& value, v8::Isolate* isolate) - { - return v8String(isolate, value); - } - }; - - template<> - struct V8ValueTraits<unsigned> { - static inline v8::Handle<v8::Value> arrayV8Value(const unsigned& value, v8::Isolate* isolate) - { - return v8::Integer::NewFromUnsigned(value, isolate); - } - }; - - template<> - struct V8ValueTraits<unsigned long> { - static inline v8::Handle<v8::Value> arrayV8Value(const unsigned long& value, v8::Isolate* isolate) - { - return v8::Integer::NewFromUnsigned(value, isolate); - } - }; - - template<> - struct V8ValueTraits<float> { - static inline v8::Handle<v8::Value> arrayV8Value(const float& value, v8::Isolate* isolate) - { - return v8::Number::New(isolate, value); - } - }; - - template<> - struct V8ValueTraits<double> { - static inline v8::Handle<v8::Value> arrayV8Value(const double& value, v8::Isolate* isolate) - { - return v8::Number::New(isolate, value); - } - }; - - template<typename T, size_t inlineCapacity> - v8::Handle<v8::Value> v8Array(const Vector<T, inlineCapacity>& iterator, v8::Isolate* isolate) +template<typename T, size_t inlineCapacity> +v8::Handle<v8::Value> v8Array(const Vector<T, inlineCapacity>& iterator, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +{ + v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size()); + int index = 0; + typename Vector<T, inlineCapacity>::const_iterator end = iterator.end(); + typedef V8ValueTraits<T> TraitsType; + for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(isolate, index++), TraitsType::toV8Value(*iter, creationContext, isolate)); + return result; +} + +template<typename T, size_t inlineCapacity> +v8::Handle<v8::Value> v8Array(const HeapVector<T, inlineCapacity>& iterator, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +{ + v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size()); + int index = 0; + typename HeapVector<T, inlineCapacity>::const_iterator end = iterator.end(); + typedef V8ValueTraits<T> TraitsType; + for (typename HeapVector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(isolate, index++), TraitsType::toV8Value(*iter, creationContext, isolate)); + return result; +} + +template<typename T, size_t inlineCapacity> +v8::Handle<v8::Value> v8ArrayNoInline(const Vector<T, inlineCapacity>& iterator, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +{ + v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size()); + int index = 0; + typename Vector<T, inlineCapacity>::const_iterator end = iterator.end(); + for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(isolate, index++), toV8NoInline(WTF::getPtr(*iter), creationContext, isolate)); + return result; +} + +template<typename T, size_t inlineCapacity> +v8::Handle<v8::Value> v8ArrayNoInline(const HeapVector<T, inlineCapacity>& iterator, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +{ + v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size()); + int index = 0; + typename HeapVector<T, inlineCapacity>::const_iterator end = iterator.end(); + for (typename HeapVector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(isolate, index++), toV8NoInline(WTF::getPtr(*iter), creationContext, isolate)); + return result; +} + +// Conversion flags, used in toIntXX/toUIntXX. +enum IntegerConversionConfiguration { + NormalConversion, + EnforceRange, + Clamp +}; + +// Convert a value to a 8-bit signed integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-byte +int8_t toInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline int8_t toInt8(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toInt8(value, NormalConversion, exceptionState); +} + +// Convert a value to a 8-bit integer assuming the conversion cannot fail. +int8_t toInt8(v8::Handle<v8::Value>); + +// Convert a value to a 8-bit unsigned integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-octet +uint8_t toUInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline uint8_t toUInt8(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toUInt8(value, NormalConversion, exceptionState); +} + +// Convert a value to a 8-bit unsigned integer assuming the conversion cannot fail. +uint8_t toUInt8(v8::Handle<v8::Value>); + +// Convert a value to a 16-bit signed integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-short +int16_t toInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline int16_t toInt16(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toInt16(value, NormalConversion, exceptionState); +} + +// Convert a value to a 16-bit integer assuming the conversion cannot fail. +int16_t toInt16(v8::Handle<v8::Value>); + +// Convert a value to a 16-bit unsigned integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-unsigned-short +uint16_t toUInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline uint16_t toUInt16(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toUInt16(value, NormalConversion, exceptionState); +} + +// Convert a value to a 16-bit unsigned integer assuming the conversion cannot fail. +uint16_t toUInt16(v8::Handle<v8::Value>); + +// Convert a value to a 32-bit signed integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-long +int32_t toInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline int32_t toInt32(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toInt32(value, NormalConversion, exceptionState); +} + +// Convert a value to a 32-bit integer assuming the conversion cannot fail. +int32_t toInt32(v8::Handle<v8::Value>); + +// Convert a value to a 32-bit unsigned integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-unsigned-long +uint32_t toUInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline uint32_t toUInt32(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toUInt32(value, NormalConversion, exceptionState); +} + +// Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail. +uint32_t toUInt32(v8::Handle<v8::Value>); + +// Convert a value to a 64-bit signed integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-long-long +int64_t toInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline int64_t toInt64(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toInt64(value, NormalConversion, exceptionState); +} + +// Convert a value to a 64-bit integer assuming the conversion cannot fail. +int64_t toInt64(v8::Handle<v8::Value>); + +// Convert a value to a 64-bit unsigned integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-unsigned-long-long +uint64_t toUInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline uint64_t toUInt64(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toUInt64(value, NormalConversion, exceptionState); +} + +// Convert a value to a 64-bit unsigned integer assuming the conversion cannot fail. +uint64_t toUInt64(v8::Handle<v8::Value>); + +// Convert a value to a single precision float, which might fail. +float toFloat(v8::Handle<v8::Value>, ExceptionState&); + +// Convert a value to a single precision float assuming the conversion cannot fail. +inline float toFloat(v8::Local<v8::Value> value) +{ + return static_cast<float>(value->NumberValue()); +} + +// Converts a value to a String, throwing if any code unit is outside 0-255. +String toByteString(v8::Handle<v8::Value>, ExceptionState&); + +// Converts a value to a String, replacing unmatched UTF-16 surrogates with replacement characters. +String toScalarValueString(v8::Handle<v8::Value>, ExceptionState&); + +inline v8::Handle<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) +{ + return value ? v8::True(isolate) : v8::False(isolate); +} + +inline double toCoreDate(v8::Handle<v8::Value> object) +{ + if (object->IsDate()) + return v8::Handle<v8::Date>::Cast(object)->ValueOf(); + if (object->IsNumber()) + return object->NumberValue(); + return std::numeric_limits<double>::quiet_NaN(); +} + +inline v8::Handle<v8::Value> v8DateOrNaN(double value, v8::Isolate* isolate) +{ + ASSERT(isolate); + return v8::Date::New(isolate, std::isfinite(value) ? value : std::numeric_limits<double>::quiet_NaN()); +} + +// FIXME: Remove the special casing for NodeFilter and XPathNSResolver. +PassRefPtrWillBeRawPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value>, v8::Handle<v8::Object>, ScriptState*); +PassRefPtrWillBeRawPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value>, v8::Isolate*); + +template<class T> struct NativeValueTraits; + +template<> +struct NativeValueTraits<String> { + static inline String nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) + { + TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, String()); + return stringValue; + } +}; + +template<> +struct NativeValueTraits<unsigned> { + static inline unsigned nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) + { + return toUInt32(value); + } +}; + +template<> +struct NativeValueTraits<float> { + static inline float nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) { - v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size()); - int index = 0; - typename Vector<T, inlineCapacity>::const_iterator end = iterator.end(); - typedef V8ValueTraits<T> TraitsType; - for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) - result->Set(v8::Integer::New(index++, isolate), TraitsType::arrayV8Value(*iter, isolate)); - return result; + return static_cast<float>(value->NumberValue()); } +}; - // Conversion flags, used in toIntXX/toUIntXX. - enum IntegerConversionConfiguration { - NormalConversion, - EnforceRange, - Clamp - }; - - // Convert a value to a 8-bit signed integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-byte - int8_t toInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline int8_t toInt8(v8::Handle<v8::Value> value, bool& ok) { return toInt8(value, NormalConversion, ok); } - - // Convert a value to a 8-bit integer assuming the conversion cannot fail. - inline int8_t toInt8(v8::Handle<v8::Value> value) +template<> +struct NativeValueTraits<double> { + static inline double nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) { - bool ok; - return toInt8(value, NormalConversion, ok); + return static_cast<double>(value->NumberValue()); } +}; - // Convert a value to a 8-bit unsigned integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-octet - uint8_t toUInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline uint8_t toUInt8(v8::Handle<v8::Value> value, bool& ok) { return toUInt8(value, NormalConversion, ok); } - - // Convert a value to a 8-bit unsigned integer assuming the conversion cannot fail. - inline uint8_t toUInt8(v8::Handle<v8::Value> value) +template<> +struct NativeValueTraits<v8::Handle<v8::Value> > { + static inline v8::Handle<v8::Value> nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) { - bool ok; - return toUInt8(value, NormalConversion, ok); + return value; } +}; - // Convert a value to a 16-bit signed integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-short - int16_t toInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline int16_t toInt16(v8::Handle<v8::Value> value, bool& ok) { return toInt16(value, NormalConversion, ok); } +v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value>, uint32_t& length, v8::Isolate*); - // Convert a value to a 16-bit integer assuming the conversion cannot fail. - inline int16_t toInt16(v8::Handle<v8::Value> value) - { - bool ok; - return toInt16(value, NormalConversion, ok); +// Converts a JavaScript value to an array as per the Web IDL specification: +// http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array +template <class T, class V8T> +Vector<RefPtr<T> > toRefPtrNativeArrayUnchecked(v8::Local<v8::Value> v8Value, uint32_t length, v8::Isolate* isolate, bool* success = 0) +{ + Vector<RefPtr<T> > result; + result.reserveInitialCapacity(length); + v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); + for (uint32_t i = 0; i < length; ++i) { + v8::Handle<v8::Value> element = object->Get(i); + if (V8T::hasInstance(element, isolate)) { + v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element); + result.uncheckedAppend(V8T::toNative(elementObject)); + } else { + if (success) + *success = false; + throwTypeError("Invalid Array element type", isolate); + return Vector<RefPtr<T> >(); + } } - - // Convert a value to a 16-bit unsigned integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-unsigned-short - uint16_t toUInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline uint16_t toUInt16(v8::Handle<v8::Value> value, bool& ok) { return toUInt16(value, NormalConversion, ok); } - - // Convert a value to a 16-bit unsigned integer assuming the conversion cannot fail. - inline uint16_t toUInt16(v8::Handle<v8::Value> value) - { - bool ok; - return toUInt16(value, NormalConversion, ok); + return result; +} + +template <class T, class V8T> +Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, bool* success = 0) +{ + if (success) + *success = true; + + v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); + uint32_t length = 0; + if (value->IsArray()) { + length = v8::Local<v8::Array>::Cast(v8Value)->Length(); + } else if (toV8Sequence(value, length, isolate).IsEmpty()) { + throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); + return Vector<RefPtr<T> >(); + } + return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success); +} + +template <class T, class V8T> +Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, const String& propertyName, v8::Isolate* isolate, bool* success = 0) +{ + if (success) + *success = true; + + v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); + uint32_t length = 0; + if (value->IsArray()) { + length = v8::Local<v8::Array>::Cast(v8Value)->Length(); + } else if (toV8Sequence(value, length, isolate).IsEmpty()) { + throwTypeError(ExceptionMessages::notASequenceTypeProperty(propertyName), isolate); + return Vector<RefPtr<T> >(); + } + return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success); +} + +template <class T, class V8T> +WillBeHeapVector<RefPtrWillBeMember<T> > toRefPtrWillBeMemberNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, bool* success = 0) +{ + if (success) + *success = true; + + v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); + uint32_t length = 0; + if (value->IsArray()) { + length = v8::Local<v8::Array>::Cast(v8Value)->Length(); + } else if (toV8Sequence(value, length, isolate).IsEmpty()) { + throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); + return WillBeHeapVector<RefPtrWillBeMember<T> >(); + } + + WillBeHeapVector<RefPtrWillBeMember<T> > result; + result.reserveInitialCapacity(length); + v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); + for (uint32_t i = 0; i < length; ++i) { + v8::Handle<v8::Value> element = object->Get(i); + if (V8T::hasInstance(element, isolate)) { + v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element); + result.uncheckedAppend(V8T::toNative(elementObject)); + } else { + if (success) + *success = false; + throwTypeError("Invalid Array element type", isolate); + return WillBeHeapVector<RefPtrWillBeMember<T> >(); + } } - - // Convert a value to a 32-bit signed integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-long - int32_t toInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline int32_t toInt32(v8::Handle<v8::Value> value, bool& ok) { return toInt32(value, NormalConversion, ok); } - - // Convert a value to a 32-bit integer assuming the conversion cannot fail. - inline int32_t toInt32(v8::Handle<v8::Value> value) + return result; +} + +// Converts a JavaScript value to an array as per the Web IDL specification: +// http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array +template <class T> +Vector<T> toNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate) +{ + v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); + uint32_t length = 0; + if (value->IsArray()) { + length = v8::Local<v8::Array>::Cast(v8Value)->Length(); + } else if (toV8Sequence(value, length, isolate).IsEmpty()) { + throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); + return Vector<T>(); + } + + Vector<T> result; + result.reserveInitialCapacity(length); + typedef NativeValueTraits<T> TraitsType; + v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); + for (uint32_t i = 0; i < length; ++i) + result.uncheckedAppend(TraitsType::nativeValue(object->Get(i), isolate)); + return result; +} + +template <class T> +Vector<T> toNativeArguments(const v8::FunctionCallbackInfo<v8::Value>& info, int startIndex) +{ + ASSERT(startIndex <= info.Length()); + Vector<T> result; + typedef NativeValueTraits<T> TraitsType; + int length = info.Length(); + result.reserveInitialCapacity(length); + for (int i = startIndex; i < length; ++i) + result.uncheckedAppend(TraitsType::nativeValue(info[i], info.GetIsolate())); + return result; +} + +// Validates that the passed object is a sequence type per WebIDL spec +// http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-sequence +inline v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value> value, uint32_t& length, v8::Isolate* isolate) +{ + // Attempt converting to a sequence if the value is not already an array but is + // any kind of object except for a native Date object or a native RegExp object. + ASSERT(!value->IsArray()); + // FIXME: Do we really need to special case Date and RegExp object? + // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22806 + if (!value->IsObject() || value->IsDate() || value->IsRegExp()) { + // The caller is responsible for reporting a TypeError. + return v8Undefined(); + } + + v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); + v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); + v8::Local<v8::String> lengthSymbol = v8AtomicString(isolate, "length"); + + // FIXME: The specification states that the length property should be used as fallback, if value + // is not a platform object that supports indexed properties. If it supports indexed properties, + // length should actually be one greater than value’s maximum indexed property index. + TONATIVE_EXCEPTION(v8::Local<v8::Value>, lengthValue, object->Get(lengthSymbol)); + + if (lengthValue->IsUndefined() || lengthValue->IsNull()) { + // The caller is responsible for reporting a TypeError. + return v8Undefined(); + } + + TONATIVE_EXCEPTION(uint32_t, sequenceLength, lengthValue->Int32Value()); + length = sequenceLength; + return v8Value; +} + +v8::Isolate* toIsolate(ExecutionContext*); +v8::Isolate* toIsolate(LocalFrame*); + +LocalDOMWindow* toDOMWindow(v8::Handle<v8::Value>, v8::Isolate*); +LocalDOMWindow* toDOMWindow(v8::Handle<v8::Context>); +LocalDOMWindow* enteredDOMWindow(v8::Isolate*); +LocalDOMWindow* currentDOMWindow(v8::Isolate*); +LocalDOMWindow* callingDOMWindow(v8::Isolate*); +ExecutionContext* toExecutionContext(v8::Handle<v8::Context>); +ExecutionContext* currentExecutionContext(v8::Isolate*); +ExecutionContext* callingExecutionContext(v8::Isolate*); + +// Returns a V8 context associated with a ExecutionContext and a DOMWrapperWorld. +// This method returns an empty context if there is no frame or the frame is already detached. +v8::Local<v8::Context> toV8Context(ExecutionContext*, DOMWrapperWorld&); +// Returns a V8 context associated with a LocalFrame and a DOMWrapperWorld. +// This method returns an empty context if the frame is already detached. +v8::Local<v8::Context> toV8Context(LocalFrame*, DOMWrapperWorld&); + +// Returns the frame object of the window object associated with +// a context, if the window is currently being displayed in the LocalFrame. +LocalFrame* toFrameIfNotDetached(v8::Handle<v8::Context>); + +// If the current context causes out of memory, JavaScript setting +// is disabled and it returns true. +bool handleOutOfMemory(); +v8::Local<v8::Value> handleMaxRecursionDepthExceeded(v8::Isolate*); +void crashIfV8IsDead(); + +inline bool isUndefinedOrNull(v8::Handle<v8::Value> value) +{ + return value->IsNull() || value->IsUndefined(); +} +v8::Handle<v8::Function> getBoundFunction(v8::Handle<v8::Function>); + +// Attaches |environment| to |function| and returns it. +inline v8::Local<v8::Function> createClosure(v8::FunctionCallback function, v8::Handle<v8::Value> environment, v8::Isolate* isolate) +{ + return v8::Function::New(isolate, function, environment); +} + +// FIXME: This will be soon embedded in the generated code. +template<class Collection> static void indexedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) +{ + Collection* collection = reinterpret_cast<Collection*>(info.Holder()->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); + int length = collection->length(); + v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), length); + for (int i = 0; i < length; ++i) { + // FIXME: Do we need to check that the item function returns a non-null value for this index? + v8::Handle<v8::Integer> integer = v8::Integer::New(info.GetIsolate(), i); + properties->Set(integer, integer); + } + v8SetReturnValue(info, properties); +} + +// These methods store hidden values into an array that is stored in the internal field of a DOM wrapper. +void addHiddenValueToArray(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex, v8::Isolate*); +void removeHiddenValueFromArray(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex, v8::Isolate*); +void moveEventListenerToNewWrapper(v8::Handle<v8::Object>, EventListener* oldValue, v8::Local<v8::Value> newValue, int cacheIndex, v8::Isolate*); + +PassRefPtr<JSONValue> v8ToJSONValue(v8::Isolate*, v8::Handle<v8::Value>, int); + +// Converts a DOM object to a v8 value. +// This is a no-inline version of toV8(). If you want to call toV8() +// without creating #include cycles, you can use this function instead. +// Each specialized implementation will be generated. +template<typename T> +v8::Handle<v8::Value> toV8NoInline(T* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*); + +// ToV8Value<U, Context> is a class that converts a C++ object to a +// v8 value. U has to be a class having a static method getCreationContext +// which returns an object created from a target context. +template<typename U, typename Context> +class ToV8Value { +public: + template<typename T> + static v8::Handle<v8::Value> toV8Value(const T& value, Context context, v8::Isolate* isolate) { - bool ok; - return toInt32(value, NormalConversion, ok); + // Default implementaion: for types that don't need the context. + return V8ValueTraits<T>::toV8Value(value, context, isolate); } - // Convert a value to a 32-bit unsigned integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-unsigned-long - uint32_t toUInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok) { return toUInt32(value, NormalConversion, ok); } - - // Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail. - inline uint32_t toUInt32(v8::Handle<v8::Value> value) + // Pointer specializations. + template<typename T> + static v8::Handle<v8::Value> toV8Value(T* const& value, Context context, v8::Isolate* isolate) { - bool ok; - return toUInt32(value, NormalConversion, ok); + return toV8NoInline(value, context, isolate); } - - // Convert a value to a 64-bit signed integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-long-long - int64_t toInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - - // Convert a value to a 64-bit integer assuming the conversion cannot fail. - inline int64_t toInt64(v8::Handle<v8::Value> value) + template<typename T> + static v8::Handle<v8::Value> toV8Value(const RefPtr<T>& value, Context context, v8::Isolate* isolate) { - bool ok; - return toInt64(value, NormalConversion, ok); + return toV8Value(value.get(), context, isolate); } - - // Convert a value to a 64-bit unsigned integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-unsigned-long-long - uint64_t toUInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - - // Convert a value to a 64-bit unsigned integer assuming the conversion cannot fail. - inline uint64_t toUInt64(v8::Handle<v8::Value> value) + template<typename T> + static v8::Handle<v8::Value> toV8Value(const PassRefPtr<T>& value, Context context, v8::Isolate* isolate) { - bool ok; - return toUInt64(value, NormalConversion, ok); + return toV8Value(value.get(), context, isolate); } - - inline float toFloat(v8::Local<v8::Value> value) + template<typename T> + static v8::Handle<v8::Value> toV8Value(const OwnPtr<T>& value, Context context, v8::Isolate* isolate) { - return static_cast<float>(value->NumberValue()); - } - - WrapperWorldType worldType(v8::Isolate*); - WrapperWorldType worldTypeInMainThread(v8::Isolate*); - - DOMWrapperWorld* isolatedWorldForIsolate(v8::Isolate*); - - template<class T> struct NativeValueTraits; - - template<> - struct NativeValueTraits<String> { - static inline String nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) - { - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, value, String()); - return stringValue; - } - }; - - template<> - struct NativeValueTraits<unsigned> { - static inline unsigned nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) - { - return toUInt32(value); - } - }; - - template<> - struct NativeValueTraits<float> { - static inline float nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) - { - return static_cast<float>(value->NumberValue()); - } - }; - - template<> - struct NativeValueTraits<double> { - static inline double nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) - { - return static_cast<double>(value->NumberValue()); - } - }; - - template<> - struct NativeValueTraits<v8::Handle<v8::Value> > { - static inline v8::Handle<v8::Value> nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) - { - return value; - } - }; - - // Converts a JavaScript value to an array as per the Web IDL specification: - // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array - template <class T, class V8T> - Vector<RefPtr<T> > toRefPtrNativeArrayUnchecked(v8::Local<v8::Value> v8Value, uint32_t length, v8::Isolate* isolate, bool* success = 0) - { - Vector<RefPtr<T> > result; - result.reserveInitialCapacity(length); - v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); - for (uint32_t i = 0; i < length; ++i) { - v8::Handle<v8::Value> element = object->Get(i); - - if (V8T::hasInstance(element, isolate, worldType(isolate))) { - v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element); - result.uncheckedAppend(V8T::toNative(elementObject)); - } else { - if (success) - *success = false; - throwTypeError("Invalid Array element type", isolate); - return Vector<RefPtr<T> >(); - } - } - return result; + return toV8Value(value.get(), context, isolate); } - - template <class T, class V8T> - Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, bool* success = 0) + template<typename T> + static v8::Handle<v8::Value> toV8Value(const PassOwnPtr<T>& value, Context context, v8::Isolate* isolate) { - if (success) - *success = true; - - v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); - uint32_t length = 0; - if (value->IsArray()) { - length = v8::Local<v8::Array>::Cast(v8Value)->Length(); - } else if (toV8Sequence(value, length, isolate).IsEmpty()) { - throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); - return Vector<RefPtr<T> >(); - } - - return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success); + return toV8Value(value.get(), context, isolate); } - - template <class T, class V8T> - Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, const String& propertyName, v8::Isolate* isolate, bool* success = 0) + template<typename T> + static v8::Handle<v8::Value> toV8Value(const RawPtr<T>& value, Context context, v8::Isolate* isolate) { - if (success) - *success = true; - - v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); - uint32_t length = 0; - if (value->IsArray()) { - length = v8::Local<v8::Array>::Cast(v8Value)->Length(); - } else if (toV8Sequence(value, length, isolate).IsEmpty()) { - throwTypeError(ExceptionMessages::notASequenceTypeProperty(propertyName), isolate); - return Vector<RefPtr<T> >(); - } - - return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success); + return toV8Value(value.get(), context, isolate); } - // Converts a JavaScript value to an array as per the Web IDL specification: - // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array - template <class T> - Vector<T> toNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate) + // const char* should use V8ValueTraits. + static v8::Handle<v8::Value> toV8Value(const char* const& value, Context context, v8::Isolate* isolate) { - v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); - uint32_t length = 0; - if (value->IsArray()) { - length = v8::Local<v8::Array>::Cast(v8Value)->Length(); - } else if (toV8Sequence(value, length, isolate).IsEmpty()) { - throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); - return Vector<T>(); - } - - Vector<T> result; - result.reserveInitialCapacity(length); - typedef NativeValueTraits<T> TraitsType; - v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); - for (uint32_t i = 0; i < length; ++i) - result.uncheckedAppend(TraitsType::nativeValue(object->Get(i), isolate)); - return result; - } - - template <class T> - Vector<T> toNativeArguments(const v8::FunctionCallbackInfo<v8::Value>& info, int startIndex) - { - ASSERT(startIndex <= info.Length()); - Vector<T> result; - typedef NativeValueTraits<T> TraitsType; - int length = info.Length(); - result.reserveInitialCapacity(length); - for (int i = startIndex; i < length; ++i) - result.uncheckedAppend(TraitsType::nativeValue(info[i], info.GetIsolate())); - return result; - } - - // Validates that the passed object is a sequence type per WebIDL spec - // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-sequence - inline v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value> value, uint32_t& length, v8::Isolate* isolate) - { - // Attempt converting to a sequence if the value is not already an array but is - // any kind of object except for a native Date object or a native RegExp object. - ASSERT(!value->IsArray()); - // FIXME: Do we really need to special case Date and RegExp object? - // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22806 - if (!value->IsObject() || value->IsDate() || value->IsRegExp()) { - // The caller is responsible for reporting a TypeError. - return v8Undefined(); - } - - v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); - v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); - v8::Local<v8::String> lengthSymbol = v8::String::NewFromUtf8(isolate, "length", v8::String::kInternalizedString, 6); - - // FIXME: The specification states that the length property should be used as fallback, if value - // is not a platform object that supports indexed properties. If it supports indexed properties, - // length should actually be one greater than value’s maximum indexed property index. - V8TRYCATCH(v8::Local<v8::Value>, lengthValue, object->Get(lengthSymbol)); - - if (lengthValue->IsUndefined() || lengthValue->IsNull()) { - // The caller is responsible for reporting a TypeError. - return v8Undefined(); - } - - V8TRYCATCH(uint32_t, sequenceLength, lengthValue->Int32Value()); - length = sequenceLength; - - return v8Value; + return V8ValueTraits<const char*>::toV8Value(value, context, isolate); } - PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value>, v8::Isolate*); - - inline bool isUndefinedOrNull(v8::Handle<v8::Value> value) + template<typename T, size_t inlineCapacity> + static v8::Handle<v8::Value> toV8Value(const Vector<T, inlineCapacity>& value, Context context, v8::Isolate* isolate) { - return value->IsNull() || value->IsUndefined(); + return v8ArrayNoInline(value, context, isolate); } - // Returns true if the provided object is to be considered a 'host object', as used in the - // HTML5 structured clone algorithm. - inline bool isHostObject(v8::Handle<v8::Object> object) + template<typename T, size_t inlineCapacity> + static v8::Handle<v8::Value> toV8Value(const HeapVector<T, inlineCapacity>& value, Context context, v8::Isolate* isolate) { - // If the object has any internal fields, then we won't be able to serialize or deserialize - // them; conveniently, this is also a quick way to detect DOM wrapper objects, because - // the mechanism for these relies on data stored in these fields. We should - // catch external array data as a special case. - return object->InternalFieldCount() || object->HasIndexedPropertiesInExternalArrayData(); + return v8ArrayNoInline(value, context, isolate); } - inline v8::Handle<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) + template<typename T, size_t inlineCapacity> + static v8::Handle<v8::Value> toV8Value(const PersistentHeapVector<T, inlineCapacity>& value, Context context, v8::Isolate* isolate) { - return value ? v8::True(isolate) : v8::False(isolate); + return v8ArrayNoInline(static_cast<HeapVector<T, inlineCapacity> >(value), context, isolate); } +}; - // Since v8Boolean(value, isolate) crashes if we pass a null isolate, - // we need to use v8BooleanWithCheck(value, isolate) if an isolate can be null. - // - // FIXME: Remove all null isolates from V8 bindings, and remove v8BooleanWithCheck(value, isolate). - inline v8::Handle<v8::Boolean> v8BooleanWithCheck(bool value, v8::Isolate* isolate) - { - return isolate ? v8Boolean(value, isolate) : v8Boolean(value, v8::Isolate::GetCurrent()); - } +// Result values for platform object 'deleter' methods, +// http://www.w3.org/TR/WebIDL/#delete +enum DeleteResult { + DeleteSuccess, + DeleteReject, + DeleteUnknownProperty +}; - inline double toWebCoreDate(v8::Handle<v8::Value> object) - { - if (object->IsDate()) - return v8::Handle<v8::Date>::Cast(object)->ValueOf(); - if (object->IsNumber()) - return object->NumberValue(); - return std::numeric_limits<double>::quiet_NaN(); - } +class V8IsolateInterruptor : public ThreadState::Interruptor { +public: + explicit V8IsolateInterruptor(v8::Isolate* isolate) : m_isolate(isolate) { } - inline v8::Handle<v8::Value> v8DateOrNull(double value, v8::Isolate* isolate) + static void onInterruptCallback(v8::Isolate* isolate, void* data) { - ASSERT(isolate); - return std::isfinite(value) ? v8::Date::New(isolate, value) : v8::Handle<v8::Value>::Cast(v8::Null(isolate)); + reinterpret_cast<V8IsolateInterruptor*>(data)->onInterrupted(); } - inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str) + virtual void requestInterrupt() OVERRIDE { - ASSERT(isolate); - return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, strlen(str)); + m_isolate->RequestInterrupt(&onInterruptCallback, this); } - inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str, size_t length) + virtual void clearInterrupt() OVERRIDE { - ASSERT(isolate); - return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, length); + m_isolate->ClearInterrupt(); } +private: + v8::Isolate* m_isolate; +}; - v8::Handle<v8::FunctionTemplate> createRawTemplate(v8::Isolate*); - - PassRefPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value>, v8::Isolate*); +class V8TestingScope { +public: + explicit V8TestingScope(v8::Isolate*); + ScriptState* scriptState() const; + v8::Isolate* isolate() const; + ~V8TestingScope(); - v8::Handle<v8::Object> toInnerGlobalObject(v8::Handle<v8::Context>); - DOMWindow* toDOMWindow(v8::Handle<v8::Context>); - ExecutionContext* toExecutionContext(v8::Handle<v8::Context>); +private: + v8::HandleScope m_handleScope; + v8::Context::Scope m_contextScope; + RefPtr<ScriptState> m_scriptState; +}; - DOMWindow* activeDOMWindow(); - ExecutionContext* activeExecutionContext(); - DOMWindow* firstDOMWindow(); - Document* currentDocument(); +void GetDevToolsFunctionInfo(v8::Handle<v8::Function>, v8::Isolate*, int& scriptId, String& resourceName, int& lineNumber); +PassRefPtr<TraceEvent::ConvertableToTraceFormat> devToolsTraceEventData(ExecutionContext*, v8::Handle<v8::Function>, v8::Isolate*); - // Returns the context associated with a ExecutionContext. - v8::Local<v8::Context> toV8Context(ExecutionContext*, DOMWrapperWorld*); - - // Returns the frame object of the window object associated with - // a context, if the window is currently being displayed in the Frame. - Frame* toFrameIfNotDetached(v8::Handle<v8::Context>); - - inline DOMWrapperWorld* isolatedWorldForEnteredContext(v8::Isolate* isolate) +class V8RethrowTryCatchScope FINAL { +public: + explicit V8RethrowTryCatchScope(v8::TryCatch& block) : m_block(block) { } + ~V8RethrowTryCatchScope() { - v8::Handle<v8::Context> context = isolate->GetEnteredContext(); - if (context.IsEmpty()) - return 0; - return DOMWrapperWorld::isolatedWorld(context); + // ReThrow() is a no-op if no exception has been caught, so always call. + m_block.ReThrow(); } - // FIXME: This will be soon embedded in the generated code. - template<class Collection> static void indexedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) - { - Collection* collection = reinterpret_cast<Collection*>(info.Holder()->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); - int length = collection->length(); - v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), length); - for (int i = 0; i < length; ++i) { - // FIXME: Do we need to check that the item function returns a non-null value for this index? - v8::Handle<v8::Integer> integer = v8::Integer::New(i, info.GetIsolate()); - properties->Set(integer, integer); - } - v8SetReturnValue(info, properties); - } - - // If the current context causes out of memory, JavaScript setting - // is disabled and it returns true. - bool handleOutOfMemory(); - v8::Local<v8::Value> handleMaxRecursionDepthExceeded(v8::Isolate*); - - void crashIfV8IsDead(); +private: + v8::TryCatch& m_block; +}; - template <class T> - v8::Handle<T> unsafeHandleFromRawValue(const T* value) +class V8ResetTryCatchScope FINAL { +public: + explicit V8ResetTryCatchScope(v8::TryCatch& block) : m_block(block) { } + ~V8ResetTryCatchScope() { - const v8::Handle<T>* handle = reinterpret_cast<const v8::Handle<T>*>(&value); - return *handle; + m_block.Reset(); } - // Attaches |environment| to |function| and returns it. - inline v8::Local<v8::Function> createClosure(v8::FunctionCallback function, v8::Handle<v8::Value> environment, v8::Isolate* isolate) - { - return v8::Function::New(isolate, function, environment); - } - - v8::Local<v8::Value> getHiddenValueFromMainWorldWrapper(v8::Isolate*, ScriptWrappable*, v8::Handle<v8::String> key); +private: + v8::TryCatch& m_block; +}; - v8::Isolate* mainThreadIsolate(); - v8::Isolate* toIsolate(ExecutionContext*); - v8::Isolate* toIsolate(Frame*); - - // Can only be called by blink::initialize - void setMainThreadIsolate(v8::Isolate*); - - // Converts a DOM object to a v8 value. - // This is a no-inline version of toV8(). If you want to call toV8() - // without creating #include cycles, you can use this function instead. - // Each specialized implementation will be generated. - template<typename T> - v8::Handle<v8::Value> toV8NoInline(T* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*); } // namespace WebCore #endif // V8Binding_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h b/chromium/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h index 8098652e209..1abb3233b80 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h @@ -33,65 +33,84 @@ namespace WebCore { -#define V8TRYCATCH(type, var, value) \ - type var; \ - { \ - v8::TryCatch block; \ - var = (value); \ - if (block.HasCaught()) \ - return block.ReThrow(); \ +// Naming scheme: +// TO*_RETURNTYPE[_ARGTYPE]... +// ...using _DEFAULT instead of _ANY..._ANY when returing a default value. + +#define TONATIVE_EXCEPTION(type, var, value) \ + type var; \ + { \ + v8::TryCatch block; \ + var = (value); \ + if (UNLIKELY(block.HasCaught())) \ + return block.ReThrow(); \ } -#define V8TRYCATCH_RETURN(type, var, value, retVal) \ - type var; \ - { \ - v8::TryCatch block; \ - var = (value); \ - if (block.HasCaught()) { \ - block.ReThrow(); \ - return retVal; \ - } \ +#define TONATIVE_VOID_INTERNAL(var, value) \ + var = (value); \ + if (UNLIKELY(block.HasCaught())) \ + return; + +#define TONATIVE_VOID(type, var, value) \ + type var; \ + { \ + v8::TryCatch block; \ + V8RethrowTryCatchScope rethrow(block); \ + TONATIVE_VOID_INTERNAL(var, value); \ } -#define V8TRYCATCH_VOID(type, var, value) \ - type var; \ - { \ - v8::TryCatch block; \ - var = (value); \ - if (block.HasCaught()) { \ - block.ReThrow(); \ - return; \ - } \ +#define TONATIVE_DEFAULT(type, var, value, retVal) \ + type var; \ + { \ + v8::TryCatch block; \ + var = (value); \ + if (UNLIKELY(block.HasCaught())) { \ + block.ReThrow(); \ + return retVal; \ + } \ } -#define V8TRYCATCH_WITH_TYPECHECK_VOID(type, var, value, isolate) \ - type var; \ - { \ - bool ok = true; \ - { \ - v8::TryCatch block; \ - var = (value); \ - if (block.HasCaught()) { \ - block.ReThrow(); \ - return; \ - } \ - } \ - if (UNLIKELY(!ok)) { \ - throwUninformativeAndGenericTypeError(isolate); \ - return; \ - } \ +#define TONATIVE_VOID_EXCEPTIONSTATE_INTERNAL(var, value, exceptionState) \ + var = (value); \ + if (UNLIKELY(block.HasCaught() || exceptionState.throwIfNeeded())) \ + return; \ + +#define TONATIVE_VOID_EXCEPTIONSTATE(type, var, value, exceptionState) \ + type var; \ + { \ + v8::TryCatch block; \ + V8RethrowTryCatchScope rethrow(block); \ + TONATIVE_VOID_EXCEPTIONSTATE_INTERNAL(var, value, exceptionState); \ } -#define V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(type, var, value, retVal) \ - type var(value); \ - if (!var.prepare()) \ - return retVal; +#define TONATIVE_DEFAULT_EXCEPTIONSTATE(type, var, value, exceptionState, retVal) \ + type var; \ + { \ + v8::TryCatch block; \ + V8RethrowTryCatchScope rethrow(block); \ + var = (value); \ + if (UNLIKELY(block.HasCaught() || exceptionState.throwIfNeeded())) \ + return retVal; \ + } + +// type is an instance of class template V8StringResource<>, +// but Mode argument varies; using type (not Mode) for consistency +// with other macros and ease of code generation +#define TOSTRING_VOID(type, var, value) \ + type var(value); \ + if (UNLIKELY(!var.prepare())) \ + return; -#define V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(type, var, value) \ - type var(value); \ - if (!var.prepare()) \ +#define TOSTRING_VOID_INTERNAL(var, value) \ + var = (value); \ + if (UNLIKELY(!var.prepare())) \ return; +#define TOSTRING_DEFAULT(type, var, value, retVal) \ + type var(value); \ + if (UNLIKELY(!var.prepare())) \ + return retVal; + } // namespace WebCore #endif // V8BindingMacros_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.cpp index ef56f45fcbc..b47b3daf58a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.cpp @@ -36,16 +36,16 @@ namespace WebCore { -bool invokeCallback(v8::Local<v8::Function> callback, int argc, v8::Handle<v8::Value> argv[], ExecutionContext* executionContext, v8::Isolate* isolate) +bool invokeCallback(ScriptState* scriptState, v8::Local<v8::Function> callback, int argc, v8::Handle<v8::Value> argv[]) { - return invokeCallback(callback, isolate->GetCurrentContext()->Global(), argc, argv, executionContext, isolate); + return invokeCallback(scriptState, callback, scriptState->context()->Global(), argc, argv); } -bool invokeCallback(v8::Local<v8::Function> callback, v8::Handle<v8::Object> thisObject, int argc, v8::Handle<v8::Value> argv[], ExecutionContext* executionContext, v8::Isolate* isolate) +bool invokeCallback(ScriptState* scriptState, v8::Local<v8::Function> callback, v8::Handle<v8::Value> thisValue, int argc, v8::Handle<v8::Value> argv[]) { v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); - ScriptController::callFunction(executionContext, callback, thisObject, argc, argv, isolate); + ScriptController::callFunction(scriptState->executionContext(), callback, thisValue, argc, argv, scriptState->isolate()); return !exceptionCatcher.HasCaught(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.h b/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.h index 6fad1b5c503..f6126243f27 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.h @@ -31,8 +31,8 @@ #ifndef V8Callback_h #define V8Callback_h +#include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "core/dom/ExceptionCode.h" #include <v8.h> @@ -41,9 +41,10 @@ namespace WebCore { class ExecutionContext; // Returns false if the callback threw an exception, true otherwise. -bool invokeCallback(v8::Local<v8::Function> callback, int argc, v8::Handle<v8::Value> argv[], ExecutionContext*, v8::Isolate*); -bool invokeCallback(v8::Local<v8::Function> callback, v8::Handle<v8::Object> thisObject, int argc, v8::Handle<v8::Value> argv[], ExecutionContext*, v8::Isolate*); +bool invokeCallback(ScriptState*, v8::Local<v8::Function> callback, int argc, v8::Handle<v8::Value> argv[]); +bool invokeCallback(ScriptState*, v8::Local<v8::Function> callback, v8::Handle<v8::Value> thisValue, int argc, v8::Handle<v8::Value> argv[]); +// FIXME: This file is used only by V8GeolocationCustom.cpp. Remove the custom binding and this file. enum CallbackAllowedValueFlag { CallbackAllowUndefined = 1, CallbackAllowNull = 1 << 1 @@ -53,7 +54,7 @@ typedef unsigned CallbackAllowedValueFlags; // 'FunctionOnly' is assumed for the created callback. template <typename V8CallbackType> -PassOwnPtr<V8CallbackType> createFunctionOnlyCallback(v8::Local<v8::Value> value, bool& succeeded, v8::Isolate* isolate, CallbackAllowedValueFlags acceptedValues = 0) +PassOwnPtr<V8CallbackType> createFunctionOnlyCallback(v8::Local<v8::Value> value, unsigned index, bool& succeeded, v8::Isolate* isolate, ExceptionState& exceptionState, CallbackAllowedValueFlags acceptedValues = 0) { succeeded = true; @@ -65,11 +66,12 @@ PassOwnPtr<V8CallbackType> createFunctionOnlyCallback(v8::Local<v8::Value> value if (!value->IsFunction()) { succeeded = false; - setDOMException(TypeMismatchError, isolate); + exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(index, "Function")); + exceptionState.throwIfNeeded(); return nullptr; } - return V8CallbackType::create(v8::Handle<v8::Function>::Cast(value), getExecutionContext()); + return V8CallbackType::create(v8::Handle<v8::Function>::Cast(value), ScriptState::current(isolate)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.cpp index 29e1bc093de..aa03363d7d9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.cpp @@ -31,14 +31,15 @@ #include "config.h" #include "bindings/v8/V8CustomElementLifecycleCallbacks.h" -#include "V8Element.h" +#include "bindings/core/v8/V8Element.h" #include "bindings/v8/CustomElementBinding.h" #include "bindings/v8/DOMDataStore.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8PerContextData.h" #include "core/dom/ExecutionContext.h" +#include "core/inspector/InspectorInstrumentation.h" #include "wtf/PassOwnPtr.h" namespace WebCore { @@ -49,20 +50,20 @@ namespace WebCore { V(detached, Detached) \ V(attributeChanged, AttributeChanged) -PassRefPtr<V8CustomElementLifecycleCallbacks> V8CustomElementLifecycleCallbacks::create(ExecutionContext* executionContext, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged) +PassRefPtr<V8CustomElementLifecycleCallbacks> V8CustomElementLifecycleCallbacks::create(ScriptState* scriptState, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged) { - v8::Isolate* isolate = toIsolate(executionContext); + v8::Isolate* isolate = scriptState->isolate(); // A given object can only be used as a Custom Element prototype // once; see customElementIsInterfacePrototypeObject -#define SET_HIDDEN_PROPERTY(Value, Name) \ - ASSERT(prototype->GetHiddenValue(V8HiddenPropertyName::customElement##Name(isolate)).IsEmpty()); \ +#define SET_HIDDEN_VALUE(Value, Name) \ + ASSERT(V8HiddenValue::getHiddenValue(isolate, prototype, V8HiddenValue::customElement##Name(isolate)).IsEmpty()); \ if (!Value.IsEmpty()) \ - prototype->SetHiddenValue(V8HiddenPropertyName::customElement##Name(isolate), Value); + V8HiddenValue::setHiddenValue(isolate, prototype, V8HiddenValue::customElement##Name(isolate), Value); - CALLBACK_LIST(SET_HIDDEN_PROPERTY) -#undef SET_HIDDEN_PROPERTY + CALLBACK_LIST(SET_HIDDEN_VALUE) +#undef SET_HIDDEN_VALUE - return adoptRef(new V8CustomElementLifecycleCallbacks(executionContext, prototype, created, attached, detached, attributeChanged)); + return adoptRef(new V8CustomElementLifecycleCallbacks(scriptState, prototype, created, attached, detached, attributeChanged)); } static CustomElementLifecycleCallbacks::CallbackType flagSet(v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged) @@ -88,16 +89,16 @@ static void weakCallback(const v8::WeakCallbackData<T, ScopedPersistent<T> >& da data.GetParameter()->clear(); } -V8CustomElementLifecycleCallbacks::V8CustomElementLifecycleCallbacks(ExecutionContext* executionContext, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged) +V8CustomElementLifecycleCallbacks::V8CustomElementLifecycleCallbacks(ScriptState* scriptState, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged) : CustomElementLifecycleCallbacks(flagSet(attached, detached, attributeChanged)) - , ActiveDOMCallback(executionContext) + , ContextLifecycleObserver(scriptState->executionContext()) , m_owner(0) - , m_world(DOMWrapperWorld::current()) - , m_prototype(toIsolate(executionContext), prototype) - , m_created(toIsolate(executionContext), created) - , m_attached(toIsolate(executionContext), attached) - , m_detached(toIsolate(executionContext), detached) - , m_attributeChanged(toIsolate(executionContext), attributeChanged) + , m_scriptState(scriptState) + , m_prototype(scriptState->isolate(), prototype) + , m_created(scriptState->isolate(), created) + , m_attached(scriptState->isolate(), attached) + , m_detached(scriptState->isolate(), detached) + , m_attributeChanged(scriptState->isolate(), attributeChanged) { m_prototype.setWeak(&m_prototype, weakCallback<v8::Object>); @@ -114,7 +115,7 @@ V8PerContextData* V8CustomElementLifecycleCallbacks::creationContextData() if (!executionContext()) return 0; - v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get()); + v8::Handle<v8::Context> context = m_scriptState->context(); if (context.IsEmpty()) return 0; @@ -126,7 +127,7 @@ V8CustomElementLifecycleCallbacks::~V8CustomElementLifecycleCallbacks() if (!m_owner) return; - v8::HandleScope handleScope(toIsolate(executionContext())); + v8::HandleScope handleScope(m_scriptState->isolate()); if (V8PerContextData* perContextData = creationContextData()) perContextData->clearCustomElementBinding(m_owner); } @@ -149,20 +150,20 @@ bool V8CustomElementLifecycleCallbacks::setBinding(CustomElementDefinition* owne void V8CustomElementLifecycleCallbacks::created(Element* element) { - if (!canInvokeCallback()) + // FIXME: callbacks while paused should be queued up for execution to + // continue then be delivered in order rather than delivered immediately. + // Bug 329665 tracks similar behavior for other synchronous events. + if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) return; element->setCustomElementState(Element::Upgraded); - v8::Isolate* isolate = toIsolate(executionContext()); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get()); - if (context.IsEmpty()) + if (m_scriptState->contextIsEmpty()) return; - - v8::Context::Scope scope(context); - - v8::Handle<v8::Object> receiver = DOMDataStore::current(isolate).get<V8Element>(element, isolate); + ScriptState::Scope scope(m_scriptState.get()); + v8::Isolate* isolate = m_scriptState->isolate(); + v8::Handle<v8::Context> context = m_scriptState->context(); + v8::Handle<v8::Object> receiver = m_scriptState->world().domDataStore().get<V8Element>(element, isolate); if (!receiver.IsEmpty()) { // Swizzle the prototype of the existing wrapper. We don't need to // worry about non-existent wrappers; they will get the right @@ -182,6 +183,8 @@ void V8CustomElementLifecycleCallbacks::created(Element* element) ASSERT(!receiver.IsEmpty()); + InspectorInstrumentation::willExecuteCustomElementCallback(element); + v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); ScriptController::callFunction(executionContext(), callback, receiver, 0, 0, isolate); @@ -199,17 +202,17 @@ void V8CustomElementLifecycleCallbacks::detached(Element* element) void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue) { - if (!canInvokeCallback()) + // FIXME: callbacks while paused should be queued up for execution to + // continue then be delivered in order rather than delivered immediately. + // Bug 329665 tracks similar behavior for other synchronous events. + if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) return; - v8::Isolate* isolate = toIsolate(executionContext()); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get()); - if (context.IsEmpty()) + if (m_scriptState->contextIsEmpty()) return; - - v8::Context::Scope scope(context); - + ScriptState::Scope scope(m_scriptState.get()); + v8::Isolate* isolate = m_scriptState->isolate(); + v8::Handle<v8::Context> context = m_scriptState->context(); v8::Handle<v8::Object> receiver = toV8(element, context->Global(), isolate).As<v8::Object>(); ASSERT(!receiver.IsEmpty()); @@ -223,6 +226,8 @@ void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const newValue.isNull() ? v8::Handle<v8::Value>(v8::Null(isolate)) : v8::Handle<v8::Value>(v8String(isolate, newValue)) }; + InspectorInstrumentation::willExecuteCustomElementCallback(element); + v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); ScriptController::callFunction(executionContext(), callback, receiver, WTF_ARRAY_LENGTH(argv), argv, isolate); @@ -230,17 +235,17 @@ void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const void V8CustomElementLifecycleCallbacks::call(const ScopedPersistent<v8::Function>& weakCallback, Element* element) { - if (!canInvokeCallback()) + // FIXME: callbacks while paused should be queued up for execution to + // continue then be delivered in order rather than delivered immediately. + // Bug 329665 tracks similar behavior for other synchronous events. + if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) return; - v8::HandleScope handleScope(toIsolate(executionContext())); - v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get()); - if (context.IsEmpty()) + if (m_scriptState->contextIsEmpty()) return; - - v8::Context::Scope scope(context); - v8::Isolate* isolate = context->GetIsolate(); - + ScriptState::Scope scope(m_scriptState.get()); + v8::Isolate* isolate = m_scriptState->isolate(); + v8::Handle<v8::Context> context = m_scriptState->context(); v8::Handle<v8::Function> callback = weakCallback.newLocal(isolate); if (callback.IsEmpty()) return; @@ -248,6 +253,8 @@ void V8CustomElementLifecycleCallbacks::call(const ScopedPersistent<v8::Function v8::Handle<v8::Object> receiver = toV8(element, context->Global(), isolate).As<v8::Object>(); ASSERT(!receiver.IsEmpty()); + InspectorInstrumentation::willExecuteCustomElementCallback(element); + v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); ScriptController::callFunction(executionContext(), callback, receiver, 0, 0, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.h b/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.h index e911e2899cc..fe32ad90ef4 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.h @@ -31,9 +31,9 @@ #ifndef V8CustomElementLifecycleCallbacks_h #define V8CustomElementLifecycleCallbacks_h -#include "bindings/v8/ActiveDOMCallback.h" -#include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScopedPersistent.h" +#include "bindings/v8/ScriptState.h" +#include "core/dom/ContextLifecycleObserver.h" #include "core/dom/custom/CustomElementLifecycleCallbacks.h" #include "wtf/PassOwnPtr.h" #include "wtf/PassRefPtr.h" @@ -46,16 +46,16 @@ class Element; class ExecutionContext; class V8PerContextData; -class V8CustomElementLifecycleCallbacks : public CustomElementLifecycleCallbacks, ActiveDOMCallback { +class V8CustomElementLifecycleCallbacks FINAL : public CustomElementLifecycleCallbacks, ContextLifecycleObserver { public: - static PassRefPtr<V8CustomElementLifecycleCallbacks> create(ExecutionContext*, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged); + static PassRefPtr<V8CustomElementLifecycleCallbacks> create(ScriptState*, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged); virtual ~V8CustomElementLifecycleCallbacks(); bool setBinding(CustomElementDefinition* owner, PassOwnPtr<CustomElementBinding>); private: - V8CustomElementLifecycleCallbacks(ExecutionContext*, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged); + V8CustomElementLifecycleCallbacks(ScriptState*, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged); virtual void created(Element*) OVERRIDE; virtual void attached(Element*) OVERRIDE; @@ -67,7 +67,7 @@ private: V8PerContextData* creationContextData(); CustomElementDefinition* m_owner; - RefPtr<DOMWrapperWorld> m_world; + RefPtr<ScriptState> m_scriptState; ScopedPersistent<v8::Object> m_prototype; ScopedPersistent<v8::Function> m_created; ScopedPersistent<v8::Function> m_attached; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.cpp new file mode 100644 index 00000000000..20ead4f4ce0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.cpp @@ -0,0 +1,72 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/v8/V8DOMActivityLogger.h" + +#include "bindings/v8/V8Binding.h" +#include "platform/weborigin/KURL.h" +#include "wtf/HashMap.h" +#include "wtf/MainThread.h" +#include "wtf/text/StringHash.h" + +namespace WebCore { + +typedef HashMap<String, OwnPtr<V8DOMActivityLogger> > DOMActivityLoggerMapForMainWorld; +typedef HashMap<int, OwnPtr<V8DOMActivityLogger>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int> > DOMActivityLoggerMapForIsolatedWorld; + +static DOMActivityLoggerMapForMainWorld& domActivityLoggersForMainWorld() +{ + ASSERT(isMainThread()); + DEFINE_STATIC_LOCAL(DOMActivityLoggerMapForMainWorld, map, ()); + return map; +} + +static DOMActivityLoggerMapForIsolatedWorld& domActivityLoggersForIsolatedWorld() +{ + ASSERT(isMainThread()); + DEFINE_STATIC_LOCAL(DOMActivityLoggerMapForIsolatedWorld, map, ()); + return map; +} + +void V8DOMActivityLogger::setActivityLogger(int worldId, const String& extensionId, PassOwnPtr<V8DOMActivityLogger> logger) +{ + if (worldId) + domActivityLoggersForIsolatedWorld().set(worldId, logger); + else + domActivityLoggersForMainWorld().set(extensionId, logger); +} + +V8DOMActivityLogger* V8DOMActivityLogger::activityLogger(int worldId, const String& extensionId) +{ + if (worldId) { + DOMActivityLoggerMapForIsolatedWorld& loggers = domActivityLoggersForIsolatedWorld(); + DOMActivityLoggerMapForIsolatedWorld::iterator it = loggers.find(worldId); + return it == loggers.end() ? 0 : it->value.get(); + } + + if (extensionId.isEmpty()) + return 0; + + DOMActivityLoggerMapForMainWorld& loggers = domActivityLoggersForMainWorld(); + DOMActivityLoggerMapForMainWorld::iterator it = loggers.find(extensionId); + return it == loggers.end() ? 0 : it->value.get(); +} + +V8DOMActivityLogger* V8DOMActivityLogger::activityLogger(int worldId, const KURL& url) +{ + // extension ID is ignored for worldId != 0. + if (worldId) + return activityLogger(worldId, String()); + + // To find an activity logger that corresponds to the main world of an + // extension, we need to obtain the extension ID. Extension ID is a hostname + // of a background page's URL. + if (!url.protocolIs("chrome-extension")) + return 0; + + return activityLogger(worldId, url.host()); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.h b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.h index 93915a65f2c..0f6b05c8e3c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.h @@ -31,16 +31,38 @@ #ifndef V8DOMActivityLogger_h #define V8DOMActivityLogger_h -#include <v8.h> +#include "wtf/PassOwnPtr.h" #include "wtf/text/WTFString.h" +#include <v8.h> namespace WebCore { +class KURL; + class V8DOMActivityLogger { public: virtual ~V8DOMActivityLogger() { } - virtual void log(const String& apiName, int argc, const v8::Handle<v8::Value>* argv, const String& extraInfo) { } + virtual void logGetter(const String& apiName) { } + virtual void logSetter(const String& apiName, const v8::Handle<v8::Value>& newValue) { } + virtual void logSetter(const String& apiName, const v8::Handle<v8::Value>& newValue, const v8::Handle<v8::Value>& oldValue) { } + virtual void logMethod(const String& apiName, int argc, const v8::Handle<v8::Value>* argv) { } + + // Associates a logger with the world identified by worldId (worlId may be 0 + // identifying the main world) and extension ID. Extension ID is used to + // identify a logger for main world only (worldId == 0). If the world is not + // a main world, an extension ID is ignored. + // + // A renderer process may host multiple extensions when the browser hits the + // renderer process limit. In such case, we assign multiple extensions to + // the same main world of a renderer process. In order to distinguish the + // extensions and their activity loggers in the main world, we require an + // extension ID. Otherwise, extension activities may be logged under + // a wrong extension ID. + static void setActivityLogger(int worldId, const String&, PassOwnPtr<V8DOMActivityLogger>); + static V8DOMActivityLogger* activityLogger(int worldId, const String& extensionId); + static V8DOMActivityLogger* activityLogger(int worldId, const KURL&); + }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.cpp index f92f9f0736e..13f2bf3659b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.cpp @@ -30,21 +30,24 @@ #include "bindings/v8/V8DOMConfiguration.h" #include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8ObjectConstructor.h" +#include "platform/TraceEvent.h" namespace WebCore { -void V8DOMConfiguration::installAttributes(v8::Handle<v8::ObjectTemplate> instanceTemplate, v8::Handle<v8::ObjectTemplate> prototype, const AttributeConfiguration* attributes, size_t attributeCount, v8::Isolate* isolate, WrapperWorldType currentWorldType) +void V8DOMConfiguration::installAttributes(v8::Handle<v8::ObjectTemplate> instanceTemplate, v8::Handle<v8::ObjectTemplate> prototype, const AttributeConfiguration* attributes, size_t attributeCount, v8::Isolate* isolate) { for (size_t i = 0; i < attributeCount; ++i) - installAttribute(instanceTemplate, prototype, attributes[i], isolate, currentWorldType); + installAttribute(instanceTemplate, prototype, attributes[i], isolate); } -void V8DOMConfiguration::installAccessors(v8::Handle<v8::ObjectTemplate> prototype, v8::Handle<v8::Signature> signature, const AccessorConfiguration* accessors, size_t accessorCount, v8::Isolate* isolate, WrapperWorldType currentWorldType) +void V8DOMConfiguration::installAccessors(v8::Handle<v8::ObjectTemplate> prototype, v8::Handle<v8::Signature> signature, const AccessorConfiguration* accessors, size_t accessorCount, v8::Isolate* isolate) { + bool isMainWorld = DOMWrapperWorld::current(isolate).isMainWorld(); for (size_t i = 0; i < accessorCount; ++i) { v8::FunctionCallback getterCallback = accessors[i].getter; v8::FunctionCallback setterCallback = accessors[i].setter; - if (currentWorldType == MainWorld) { + if (isMainWorld) { if (accessors[i].getterForMainWorld) getterCallback = accessors[i].getterForMainWorld; if (accessors[i].setterForMainWorld) @@ -61,7 +64,7 @@ void V8DOMConfiguration::installAccessors(v8::Handle<v8::ObjectTemplate> prototy setter = v8::FunctionTemplate::New(isolate, setterCallback, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(accessors[i].data)), signature, 1); setter->RemovePrototype(); } - prototype->SetAccessorProperty(v8::String::NewFromUtf8(isolate, accessors[i].name, v8::String::kInternalizedString), getter, setter, accessors[i].attribute, accessors[i].settings); + prototype->SetAccessorProperty(v8AtomicString(isolate, accessors[i].name), getter, setter, accessors[i].attribute, accessors[i].settings); } } @@ -69,20 +72,22 @@ void V8DOMConfiguration::installConstants(v8::Handle<v8::FunctionTemplate> funct { for (size_t i = 0; i < constantCount; ++i) { const ConstantConfiguration* constant = &constants[i]; - functionDescriptor->Set(v8::String::NewFromUtf8(isolate, constant->name, v8::String::kInternalizedString), v8::Integer::New(isolate, constant->value), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); - prototype->Set(v8::String::NewFromUtf8(isolate, constant->name, v8::String::kInternalizedString), v8::Integer::New(isolate, constant->value), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); + v8::Handle<v8::String> constantName = v8AtomicString(isolate, constant->name); + functionDescriptor->Set(constantName, v8::Integer::New(isolate, constant->value), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); + prototype->Set(constantName, v8::Integer::New(isolate, constant->value), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); } } -void V8DOMConfiguration::installCallbacks(v8::Handle<v8::ObjectTemplate> prototype, v8::Handle<v8::Signature> signature, v8::PropertyAttribute attributes, const MethodConfiguration* callbacks, size_t callbackCount, v8::Isolate* isolate, WrapperWorldType currentWorldType) +void V8DOMConfiguration::installCallbacks(v8::Handle<v8::ObjectTemplate> prototype, v8::Handle<v8::Signature> signature, v8::PropertyAttribute attributes, const MethodConfiguration* callbacks, size_t callbackCount, v8::Isolate* isolate) { + bool isMainWorld = DOMWrapperWorld::current(isolate).isMainWorld(); for (size_t i = 0; i < callbackCount; ++i) { v8::FunctionCallback callback = callbacks[i].callback; - if (currentWorldType == MainWorld && callbacks[i].callbackForMainWorld) + if (isMainWorld && callbacks[i].callbackForMainWorld) callback = callbacks[i].callbackForMainWorld; v8::Local<v8::FunctionTemplate> functionTemplate = v8::FunctionTemplate::New(isolate, callback, v8Undefined(), signature, callbacks[i].length); functionTemplate->RemovePrototype(); - prototype->Set(v8::String::NewFromUtf8(isolate, callbacks[i].name, v8::String::kInternalizedString), functionTemplate, attributes); + prototype->Set(v8AtomicString(isolate, callbacks[i].name), functionTemplate, attributes); } } @@ -90,9 +95,9 @@ v8::Local<v8::Signature> V8DOMConfiguration::installDOMClassTemplate(v8::Handle< const AttributeConfiguration* attributes, size_t attributeCount, const AccessorConfiguration* accessors, size_t accessorCount, const MethodConfiguration* callbacks, size_t callbackCount, - v8::Isolate* isolate, WrapperWorldType currentWorldType) + v8::Isolate* isolate) { - functionDescriptor->SetClassName(v8::String::NewFromUtf8(isolate, interfaceName, v8::String::kInternalizedString)); + functionDescriptor->SetClassName(v8AtomicString(isolate, interfaceName)); v8::Local<v8::ObjectTemplate> instanceTemplate = functionDescriptor->InstanceTemplate(); instanceTemplate->SetInternalFieldCount(fieldCount); if (!parentClass.IsEmpty()) { @@ -106,12 +111,26 @@ v8::Local<v8::Signature> V8DOMConfiguration::installDOMClassTemplate(v8::Handle< v8::Local<v8::Signature> defaultSignature = v8::Signature::New(isolate, functionDescriptor); if (attributeCount) - installAttributes(instanceTemplate, functionDescriptor->PrototypeTemplate(), attributes, attributeCount, isolate, currentWorldType); + installAttributes(instanceTemplate, functionDescriptor->PrototypeTemplate(), attributes, attributeCount, isolate); if (accessorCount) - installAccessors(functionDescriptor->PrototypeTemplate(), defaultSignature, accessors, accessorCount, isolate, currentWorldType); + installAccessors(functionDescriptor->PrototypeTemplate(), defaultSignature, accessors, accessorCount, isolate); if (callbackCount) - installCallbacks(functionDescriptor->PrototypeTemplate(), defaultSignature, static_cast<v8::PropertyAttribute>(v8::DontDelete), callbacks, callbackCount, isolate, currentWorldType); + installCallbacks(functionDescriptor->PrototypeTemplate(), defaultSignature, static_cast<v8::PropertyAttribute>(v8::DontDelete), callbacks, callbackCount, isolate); return defaultSignature; } +v8::Handle<v8::FunctionTemplate> V8DOMConfiguration::domClassTemplate(v8::Isolate* isolate, WrapperTypeInfo* wrapperTypeInfo, void (*configureDOMClassTemplate)(v8::Handle<v8::FunctionTemplate>, v8::Isolate*)) +{ + V8PerIsolateData* data = V8PerIsolateData::from(isolate); + v8::Local<v8::FunctionTemplate> result = data->existingDOMTemplate(wrapperTypeInfo); + if (!result.IsEmpty()) + return result; + + TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); + result = v8::FunctionTemplate::New(isolate, V8ObjectConstructor::isValidConstructorMode); + configureDOMClassTemplate(result, isolate); + data->setDOMTemplate(wrapperTypeInfo, result); + return result; +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.h b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.h index 18a2e3bf0d5..28b1e504aef 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.h @@ -69,25 +69,14 @@ public: v8::PropertyAttribute attribute; }; - static void installAttributes(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::ObjectTemplate>, const AttributeConfiguration*, size_t attributeCount, v8::Isolate*, WrapperWorldType currentWorldType); + static void installAttributes(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::ObjectTemplate>, const AttributeConfiguration*, size_t attributeCount, v8::Isolate*); template<class ObjectOrTemplate> static inline void installAttribute(v8::Handle<ObjectOrTemplate> instanceTemplate, v8::Handle<ObjectOrTemplate> prototype, const AttributeConfiguration& attribute, v8::Isolate* isolate) { - (attribute.onPrototype ? prototype : instanceTemplate)->SetAccessor(v8::String::NewFromUtf8(isolate, attribute.name, v8::String::kInternalizedString), - attribute.getter, - attribute.setter, - v8::External::New(isolate, const_cast<WrapperTypeInfo*>(attribute.data)), - attribute.settings, - attribute.attribute); - } - - template<class ObjectOrTemplate> - static inline void installAttribute(v8::Handle<ObjectOrTemplate> instanceTemplate, v8::Handle<ObjectOrTemplate> prototype, const AttributeConfiguration& attribute, v8::Isolate* isolate, WrapperWorldType currentWorldType) - { v8::AccessorGetterCallback getter = attribute.getter; v8::AccessorSetterCallback setter = attribute.setter; - if (currentWorldType == MainWorld) { + if (DOMWrapperWorld::current(isolate).isMainWorld()) { if (attribute.getterForMainWorld) getter = attribute.getterForMainWorld; if (attribute.setterForMainWorld) @@ -120,15 +109,17 @@ public: int length; }; - static void installCallbacks(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Signature>, v8::PropertyAttribute, const MethodConfiguration*, size_t callbackCount, v8::Isolate*, WrapperWorldType); + static void installCallbacks(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Signature>, v8::PropertyAttribute, const MethodConfiguration*, size_t callbackCount, v8::Isolate*); - static void installAccessors(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Signature>, const AccessorConfiguration*, size_t accessorCount, v8::Isolate*, WrapperWorldType); + static void installAccessors(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Signature>, const AccessorConfiguration*, size_t accessorCount, v8::Isolate*); static v8::Local<v8::Signature> installDOMClassTemplate(v8::Handle<v8::FunctionTemplate>, const char* interfaceName, v8::Handle<v8::FunctionTemplate> parentClass, size_t fieldCount, const AttributeConfiguration*, size_t attributeCount, const AccessorConfiguration*, size_t accessorCount, const MethodConfiguration*, size_t callbackCount, - v8::Isolate*, WrapperWorldType); + v8::Isolate*); + + static v8::Handle<v8::FunctionTemplate> domClassTemplate(v8::Isolate*, WrapperTypeInfo*, void (*)(v8::Handle<v8::FunctionTemplate>, v8::Isolate*)); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.cpp index 41dca146507..8a52d8c4296 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.cpp @@ -31,11 +31,10 @@ #include "config.h" #include "bindings/v8/V8DOMWrapper.h" -#include "V8HTMLCollection.h" -#include "V8HTMLDocument.h" -#include "V8Window.h" +#include "bindings/core/v8/V8HTMLCollection.h" +#include "bindings/core/v8/V8HTMLDocument.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" #include "bindings/v8/V8ObjectConstructor.h" #include "bindings/v8/V8PerContextData.h" #include "bindings/v8/V8ScriptRunner.h" @@ -44,30 +43,28 @@ namespace WebCore { static v8::Local<v8::Object> wrapInShadowTemplate(v8::Local<v8::Object> wrapper, Node* impl, v8::Isolate* isolate) { - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int shadowTemplateUniqueKey; - WrapperWorldType currentWorldType = worldType(isolate); + static int shadowTemplateKey; // This address is used for a key to look up the dom template. V8PerIsolateData* data = V8PerIsolateData::from(isolate); - v8::Handle<v8::FunctionTemplate> shadowTemplate = data->privateTemplateIfExists(currentWorldType, &shadowTemplateUniqueKey); + v8::Handle<v8::FunctionTemplate> shadowTemplate = data->existingDOMTemplate(&shadowTemplateKey); if (shadowTemplate.IsEmpty()) { shadowTemplate = v8::FunctionTemplate::New(isolate); if (shadowTemplate.IsEmpty()) return v8::Local<v8::Object>(); shadowTemplate->SetClassName(v8AtomicString(isolate, "HTMLDocument")); - shadowTemplate->Inherit(V8HTMLDocument::domTemplate(isolate, currentWorldType)); + shadowTemplate->Inherit(V8HTMLDocument::domTemplate(isolate)); shadowTemplate->InstanceTemplate()->SetInternalFieldCount(V8HTMLDocument::internalFieldCount); - data->setPrivateTemplate(currentWorldType, &shadowTemplateUniqueKey, shadowTemplate); + data->setDOMTemplate(&shadowTemplateKey, shadowTemplate); } v8::Local<v8::Function> shadowConstructor = shadowTemplate->GetFunction(); if (shadowConstructor.IsEmpty()) return v8::Local<v8::Object>(); - v8::Local<v8::Object> shadow = V8ScriptRunner::instantiateObject(shadowConstructor); + v8::Local<v8::Object> shadow = V8ScriptRunner::instantiateObject(isolate, shadowConstructor); if (shadow.IsEmpty()) return v8::Local<v8::Object>(); shadow->SetPrototype(wrapper); - V8DOMWrapper::setNativeInfo(wrapper, &V8HTMLDocument::wrapperTypeInfo, impl); + V8DOMWrapper::setNativeInfoForHiddenWrapper(wrapper, &V8HTMLDocument::wrapperTypeInfo, impl); return shadow; } @@ -76,7 +73,7 @@ v8::Local<v8::Object> V8DOMWrapper::createWrapper(v8::Handle<v8::Object> creatio V8WrapperInstantiationScope scope(creationContext, isolate); V8PerContextData* perContextData = V8PerContextData::from(scope.context()); - v8::Local<v8::Object> wrapper = perContextData ? perContextData->createWrapperFromCache(type) : V8ObjectConstructor::newInstance(type->domTemplate(isolate, worldTypeInMainThread(isolate))->GetFunction()); + v8::Local<v8::Object> wrapper = perContextData ? perContextData->createWrapperFromCache(type) : V8ObjectConstructor::newInstance(isolate, type->domTemplate(isolate)->GetFunction()); if (type == &V8HTMLDocument::wrapperTypeInfo && !wrapper.IsEmpty()) wrapper = wrapInShadowTemplate(wrapper, static_cast<Node*>(impl), isolate); @@ -84,59 +81,22 @@ v8::Local<v8::Object> V8DOMWrapper::createWrapper(v8::Handle<v8::Object> creatio return wrapper; } -static bool hasInternalField(v8::Handle<v8::Value> value) +bool V8DOMWrapper::isDOMWrapper(v8::Handle<v8::Value> value) { if (value.IsEmpty() || !value->IsObject()) return false; - return v8::Handle<v8::Object>::Cast(value)->InternalFieldCount(); -} -#ifndef NDEBUG -bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) -{ - if (!hasInternalField(value)) - return false; - - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); - ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); - - v8::HandleScope scope(v8::Isolate::GetCurrent()); - ASSERT(object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); - - const WrapperTypeInfo* typeInfo = static_cast<const WrapperTypeInfo*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex)); - - return typeInfo->ginEmbedder == gin::kEmbedderBlink; -} -#endif - -bool V8DOMWrapper::isDOMWrapper(v8::Handle<v8::Value> value) -{ - if (value.IsEmpty() || !value->IsObject()) + if (v8::Handle<v8::Object>::Cast(value)->InternalFieldCount() < v8DefaultWrapperInternalFieldCount) return false; v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(value); - if (wrapper->InternalFieldCount() < v8DefaultWrapperInternalFieldCount) - return false; ASSERT(wrapper->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); ASSERT(wrapper->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex)); const WrapperTypeInfo* typeInfo = static_cast<const WrapperTypeInfo*>(wrapper->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex)); - - // FIXME: Add class id checks. + // FIXME: We should add a more strict way to check if the typeInfo is a typeInfo of some DOM wrapper. + // Even if it's a typeInfo of Blink, it's not guaranteed that it's a typeInfo of a DOM wrapper. return typeInfo->ginEmbedder == gin::kEmbedderBlink; } -bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, const WrapperTypeInfo* type) -{ - if (!hasInternalField(value)) - return false; - - v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(value); - ASSERT(wrapper->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); - ASSERT(wrapper->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); - - const WrapperTypeInfo* typeInfo = static_cast<const WrapperTypeInfo*>(wrapper->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex)); - return typeInfo->ginEmbedder == gin::kEmbedderBlink && typeInfo == type; -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.h b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.h index 4bda879805b..db41c8f9034 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.h @@ -34,6 +34,7 @@ #include "bindings/v8/DOMDataStore.h" #include <v8.h> #include "wtf/PassRefPtr.h" +#include "wtf/RawPtr.h" #include "wtf/text/AtomicString.h" namespace WebCore { @@ -42,60 +43,115 @@ struct WrapperTypeInfo; class V8DOMWrapper { public: -#ifndef NDEBUG - // Checks if a v8 value can be a DOM wrapper - static bool maybeDOMWrapper(v8::Handle<v8::Value>); -#endif - static v8::Local<v8::Object> createWrapper(v8::Handle<v8::Object> creationContext, const WrapperTypeInfo*, void*, v8::Isolate*); template<typename V8T, typename T> static inline v8::Handle<v8::Object> associateObjectWithWrapper(PassRefPtr<T>, const WrapperTypeInfo*, v8::Handle<v8::Object>, v8::Isolate*, WrapperConfiguration::Lifetime); + template<typename V8T, typename T> + static inline v8::Handle<v8::Object> associateObjectWithWrapper(RawPtr<T> object, const WrapperTypeInfo* wrapperTypeInfo, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, WrapperConfiguration::Lifetime lifetime) + { + return associateObjectWithWrapper<V8T, T>(object.get(), wrapperTypeInfo, wrapper, isolate, lifetime); + } + template<typename V8T, typename T> + static inline v8::Handle<v8::Object> associateObjectWithWrapper(T*, const WrapperTypeInfo*, v8::Handle<v8::Object>, v8::Isolate*, WrapperConfiguration::Lifetime); static inline void setNativeInfo(v8::Handle<v8::Object>, const WrapperTypeInfo*, void*); + static inline void setNativeInfoForHiddenWrapper(v8::Handle<v8::Object>, const WrapperTypeInfo*, void*); + static inline void setNativeInfoWithPersistentHandle(v8::Handle<v8::Object>, const WrapperTypeInfo*, void*, PersistentNode*); static inline void clearNativeInfo(v8::Handle<v8::Object>, const WrapperTypeInfo*); static bool isDOMWrapper(v8::Handle<v8::Value>); - static bool isWrapperOfType(v8::Handle<v8::Value>, const WrapperTypeInfo*); }; - inline void V8DOMWrapper::setNativeInfo(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* type, void* object) + inline void V8DOMWrapper::setNativeInfo(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* wrapperTypeInfo, void* object) + { + ASSERT(wrapper->InternalFieldCount() >= 2); + ASSERT(object); + ASSERT(wrapperTypeInfo); +#if ENABLE(OILPAN) + ASSERT(wrapperTypeInfo->gcType == RefCountedObject); +#else + ASSERT(wrapperTypeInfo->gcType == RefCountedObject || wrapperTypeInfo->gcType == WillBeGarbageCollectedObject); +#endif + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperObjectIndex, object); + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(wrapperTypeInfo)); + } + + inline void V8DOMWrapper::setNativeInfoForHiddenWrapper(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* wrapperTypeInfo, void* object) { + // see V8WindowShell::installDOMWindow() comment for why this version is needed and safe. ASSERT(wrapper->InternalFieldCount() >= 2); ASSERT(object); - ASSERT(type); + ASSERT(wrapperTypeInfo); +#if ENABLE(OILPAN) + ASSERT(wrapperTypeInfo->gcType != RefCountedObject); +#else + ASSERT(wrapperTypeInfo->gcType == RefCountedObject || wrapperTypeInfo->gcType == WillBeGarbageCollectedObject); +#endif + + // Clear out the last internal field, which is assumed to contain a valid persistent pointer value. + if (wrapperTypeInfo->gcType == GarbageCollectedObject) { + wrapper->SetAlignedPointerInInternalField(wrapper->InternalFieldCount() - 1, 0); + } else if (wrapperTypeInfo->gcType == WillBeGarbageCollectedObject) { +#if ENABLE(OILPAN) + wrapper->SetAlignedPointerInInternalField(wrapper->InternalFieldCount() - 1, 0); +#endif + } + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperObjectIndex, object); + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(wrapperTypeInfo)); + } + + inline void V8DOMWrapper::setNativeInfoWithPersistentHandle(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* wrapperTypeInfo, void* object, PersistentNode* handle) + { + ASSERT(wrapper->InternalFieldCount() >= 3); + ASSERT(object); + ASSERT(wrapperTypeInfo); + ASSERT(wrapperTypeInfo->gcType != RefCountedObject); wrapper->SetAlignedPointerInInternalField(v8DOMWrapperObjectIndex, object); - wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(type)); + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(wrapperTypeInfo)); + // Persistent handle is stored in the last internal field. + wrapper->SetAlignedPointerInInternalField(wrapper->InternalFieldCount() - 1, handle); } - inline void V8DOMWrapper::clearNativeInfo(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* type) + inline void V8DOMWrapper::clearNativeInfo(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* wrapperTypeInfo) { ASSERT(wrapper->InternalFieldCount() >= 2); - ASSERT(type); - wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(type)); + ASSERT(wrapperTypeInfo); + // clearNativeInfo() is used only by NP objects, which are not garbage collected. + ASSERT(wrapperTypeInfo->gcType == RefCountedObject); + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(wrapperTypeInfo)); wrapper->SetAlignedPointerInInternalField(v8DOMWrapperObjectIndex, 0); } template<typename V8T, typename T> - inline v8::Handle<v8::Object> V8DOMWrapper::associateObjectWithWrapper(PassRefPtr<T> object, const WrapperTypeInfo* type, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, WrapperConfiguration::Lifetime lifetime) + inline v8::Handle<v8::Object> V8DOMWrapper::associateObjectWithWrapper(PassRefPtr<T> object, const WrapperTypeInfo* wrapperTypeInfo, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, WrapperConfiguration::Lifetime lifetime) { - setNativeInfo(wrapper, type, V8T::toInternalPointer(object.get())); - ASSERT(maybeDOMWrapper(wrapper)); + setNativeInfo(wrapper, wrapperTypeInfo, V8T::toInternalPointer(object.get())); + ASSERT(isDOMWrapper(wrapper)); WrapperConfiguration configuration = buildWrapperConfiguration(object.get(), lifetime); DOMDataStore::setWrapper<V8T>(object.leakRef(), wrapper, isolate, configuration); return wrapper; } + template<typename V8T, typename T> + inline v8::Handle<v8::Object> V8DOMWrapper::associateObjectWithWrapper(T* object, const WrapperTypeInfo* wrapperTypeInfo, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, WrapperConfiguration::Lifetime lifetime) + { + setNativeInfoWithPersistentHandle(wrapper, wrapperTypeInfo, V8T::toInternalPointer(object), new Persistent<T>(object)); + ASSERT(isDOMWrapper(wrapper)); + WrapperConfiguration configuration = buildWrapperConfiguration(object, lifetime); + DOMDataStore::setWrapper<V8T>(object, wrapper, isolate, configuration); + return wrapper; + } + class V8WrapperInstantiationScope { public: V8WrapperInstantiationScope(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) : m_didEnterContext(false) , m_context(isolate->GetCurrentContext()) { - // FIXME: Remove all empty creationContexts from caller sites. - // If a creationContext is empty, we will end up creating a new object - // in the context currently entered. This is wrong. - if (creationContext.IsEmpty()) - return; + // creationContext should not be empty. Because if we have an + // empty creationContext, we will end up creating + // a new object in the context currently entered. This is wrong. + RELEASE_ASSERT(!creationContext.IsEmpty()); v8::Handle<v8::Context> contextForWrapper = creationContext->CreationContext(); // For performance, we enter the context only if the currently running context // is different from the context that we are about to enter. diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.cpp index 758eb47fedf..c72ac25806b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.cpp @@ -31,63 +31,61 @@ #include "config.h" #include "bindings/v8/V8ErrorHandler.h" -#include "V8ErrorEvent.h" +#include "bindings/core/v8/V8ErrorEvent.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8ScriptRunner.h" #include "core/dom/Document.h" #include "core/dom/ExecutionContext.h" #include "core/events/ErrorEvent.h" -#include "core/events/ThreadLocalEventNames.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -V8ErrorHandler::V8ErrorHandler(v8::Local<v8::Object> listener, bool isInline, v8::Isolate* isolate) - : V8EventListener(listener, isInline, isolate) +V8ErrorHandler::V8ErrorHandler(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) + : V8EventListener(listener, isInline, scriptState) { } -v8::Local<v8::Value> V8ErrorHandler::callListenerFunction(ExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) +v8::Local<v8::Value> V8ErrorHandler::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { if (!event->hasInterface(EventNames::ErrorEvent)) - return V8EventListener::callListenerFunction(context, jsEvent, event); + return V8EventListener::callListenerFunction(jsEvent, event); ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event); - v8::Isolate* isolate = toV8Context(context, world())->GetIsolate(); - if (errorEvent->world() && errorEvent->world() != world()) - return v8::Null(isolate); + if (errorEvent->world() && errorEvent->world() != &world()) + return v8::Null(isolate()); - v8::Local<v8::Object> listener = getListenerObject(context); + v8::Local<v8::Object> listener = getListenerObject(scriptState()->executionContext()); v8::Local<v8::Value> returnValue; if (!listener.IsEmpty() && listener->IsFunction()) { v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); - v8::Local<v8::Object> thisValue = isolate->GetCurrentContext()->Global(); + v8::Local<v8::Object> thisValue = scriptState()->context()->Global(); - v8::Local<v8::Value> error = jsEvent->ToObject()->GetHiddenValue(V8HiddenPropertyName::error(isolate)); + v8::Local<v8::Value> error = V8HiddenValue::getHiddenValue(isolate(), jsEvent->ToObject(), V8HiddenValue::error(isolate())); if (error.IsEmpty()) - error = v8::Null(isolate); + error = v8::Null(isolate()); - v8::Handle<v8::Value> parameters[5] = { v8String(isolate, errorEvent->message()), v8String(isolate, errorEvent->filename()), v8::Integer::New(errorEvent->lineno(), isolate), v8::Integer::New(errorEvent->colno(), isolate), error }; + v8::Handle<v8::Value> parameters[5] = { v8String(isolate(), errorEvent->message()), v8String(isolate(), errorEvent->filename()), v8::Integer::New(isolate(), errorEvent->lineno()), v8::Integer::New(isolate(), errorEvent->colno()), error }; v8::TryCatch tryCatch; tryCatch.SetVerbose(true); - if (worldType(isolate) == WorkerWorld) - returnValue = V8ScriptRunner::callFunction(callFunction, context, thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate); + if (scriptState()->executionContext()->isWorkerGlobalScope()) + returnValue = V8ScriptRunner::callFunction(callFunction, scriptState()->executionContext(), thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate()); else - returnValue = ScriptController::callFunction(context, callFunction, thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate); + returnValue = ScriptController::callFunction(scriptState()->executionContext(), callFunction, thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate()); } return returnValue; } // static -void V8ErrorHandler::storeExceptionOnErrorEventWrapper(ErrorEvent* event, v8::Handle<v8::Value> data, v8::Isolate* isolate) +void V8ErrorHandler::storeExceptionOnErrorEventWrapper(ErrorEvent* event, v8::Handle<v8::Value> data, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { - v8::Local<v8::Value> wrappedEvent = toV8(event, v8::Handle<v8::Object>(), isolate); + v8::Local<v8::Value> wrappedEvent = toV8(event, creationContext, isolate); if (!wrappedEvent.IsEmpty()) { ASSERT(wrappedEvent->IsObject()); - v8::Local<v8::Object>::Cast(wrappedEvent)->SetHiddenValue(V8HiddenPropertyName::error(isolate), data); + V8HiddenValue::setHiddenValue(isolate, v8::Local<v8::Object>::Cast(wrappedEvent), V8HiddenValue::error(isolate), data); } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.h b/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.h index cfaa69de587..8e1d5f22489 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.h @@ -38,22 +38,22 @@ namespace WebCore { class ErrorEvent; -class Frame; +class LocalFrame; -class V8ErrorHandler : public V8EventListener { +class V8ErrorHandler FINAL : public V8EventListener { public: - static PassRefPtr<V8ErrorHandler> create(v8::Local<v8::Object> listener, bool isInline, v8::Isolate* isolate) + static PassRefPtr<V8ErrorHandler> create(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) { - return adoptRef(new V8ErrorHandler(listener, isInline, isolate)); + return adoptRef(new V8ErrorHandler(listener, isInline, scriptState)); } - static void storeExceptionOnErrorEventWrapper(ErrorEvent*, v8::Handle<v8::Value>, v8::Isolate*); + static void storeExceptionOnErrorEventWrapper(ErrorEvent*, v8::Handle<v8::Value>, v8::Handle<v8::Object> creationContext, v8::Isolate*); private: - V8ErrorHandler(v8::Local<v8::Object> listener, bool isInline, v8::Isolate*); + V8ErrorHandler(v8::Local<v8::Object> listener, bool isInline, ScriptState*); - virtual v8::Local<v8::Value> callListenerFunction(ExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); - virtual bool shouldPreventDefault(v8::Local<v8::Value> returnValue); + virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*) OVERRIDE; + virtual bool shouldPreventDefault(v8::Local<v8::Value> returnValue) OVERRIDE; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.cpp index 13144b96e9d..fc204607cee 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.cpp @@ -34,19 +34,19 @@ #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" #include "core/dom/Document.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -V8EventListener::V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, v8::Isolate* isolate) - : V8AbstractEventListener(isAttribute, DOMWrapperWorld::current(), isolate) +V8EventListener::V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, ScriptState* scriptState) + : V8AbstractEventListener(isAttribute, scriptState) { setListenerObject(listener); } -v8::Local<v8::Function> V8EventListener::getListenerFunction(ExecutionContext* context) +v8::Local<v8::Function> V8EventListener::getListenerFunction(ExecutionContext*) { - v8::Local<v8::Object> listener = getListenerObject(context); + v8::Local<v8::Object> listener = getListenerObject(scriptState()->executionContext()); // Has the listener been disposed? if (listener.IsEmpty()) @@ -67,22 +67,18 @@ v8::Local<v8::Function> V8EventListener::getListenerFunction(ExecutionContext* c return v8::Local<v8::Function>(); } -v8::Local<v8::Value> V8EventListener::callListenerFunction(ExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) +v8::Local<v8::Value> V8EventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { - v8::Local<v8::Function> handlerFunction = getListenerFunction(context); - v8::Local<v8::Object> receiver = getReceiverObject(context, event); + v8::Local<v8::Function> handlerFunction = getListenerFunction(scriptState()->executionContext()); + v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); - // FIXME: Can |context| be 0 here? - if (!context) + if (!scriptState()->executionContext()->isDocument()) return v8::Local<v8::Value>(); - if (!context->isDocument()) - return v8::Local<v8::Value>(); - - Frame* frame = toDocument(context)->frame(); + LocalFrame* frame = toDocument(scriptState()->executionContext())->frame(); if (!frame) return v8::Local<v8::Value>(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.h b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.h index 1358848a5f1..93296ae659e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.h @@ -31,7 +31,6 @@ #ifndef V8EventListener_h #define V8EventListener_h -#include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/V8AbstractEventListener.h" #include <v8.h> #include "wtf/PassRefPtr.h" @@ -39,23 +38,23 @@ namespace WebCore { class Event; - class Frame; + class LocalFrame; // V8EventListener is a wrapper of a JS object implements EventListener interface (has handleEvent(event) method), or a JS function // that can handle the event. class V8EventListener : public V8AbstractEventListener { public: - static PassRefPtr<V8EventListener> create(v8::Local<v8::Object> listener, bool isAttribute, v8::Isolate* isolate) + static PassRefPtr<V8EventListener> create(v8::Local<v8::Object> listener, bool isAttribute, ScriptState* scriptState) { - return adoptRef(new V8EventListener(listener, isAttribute, isolate)); + return adoptRef(new V8EventListener(listener, isAttribute, scriptState)); } protected: - V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, v8::Isolate*); + V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, ScriptState*); v8::Local<v8::Function> getListenerFunction(ExecutionContext*); - virtual v8::Local<v8::Value> callListenerFunction(ExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); + virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*) OVERRIDE; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.cpp index 0606fb69fa6..ad44ef8bd1f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.cpp @@ -31,27 +31,24 @@ #include "config.h" #include "bindings/v8/V8EventListenerList.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8WorkerGlobalScopeEventListener.h" namespace WebCore { -PassRefPtr<EventListener> V8EventListenerList::getEventListener(v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +PassRefPtr<EventListener> V8EventListenerList::getEventListener(ScriptState* scriptState, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::Handle<v8::Context> context = isolate->GetCurrentContext(); - if (context.IsEmpty()) - return 0; + ASSERT(!scriptState->contextIsEmpty()); if (lookup == ListenerFindOnly) { // Used by EventTarget::removeEventListener, specifically // EventTargetV8Internal::removeEventListenerMethod ASSERT(!isAttribute); - return V8EventListenerList::findWrapper(value, isolate); + return V8EventListenerList::findWrapper(value, scriptState); } - if (V8DOMWrapper::isWrapperOfType(toInnerGlobalObject(context), &V8Window::wrapperTypeInfo)) - return V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute, isolate); - return V8EventListenerList::findOrCreateWrapper<V8WorkerGlobalScopeEventListener>(value, isAttribute, isolate); + if (toDOMWindow(scriptState->context())) + return V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute, scriptState); + return V8EventListenerList::findOrCreateWrapper<V8WorkerGlobalScopeEventListener>(value, isAttribute, scriptState); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.h b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.h index 3be3bb9f34f..34ee4106e01 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.h @@ -31,15 +31,13 @@ #ifndef V8EventListenerList_h #define V8EventListenerList_h +#include "bindings/v8/V8Binding.h" #include "bindings/v8/V8EventListener.h" -#include "bindings/v8/V8HiddenPropertyName.h" - #include <v8.h> -#include "wtf/PassRefPtr.h" namespace WebCore { -class Frame; +class LocalFrame; enum ListenerLookupType { ListenerFindOnly, @@ -49,18 +47,18 @@ enum ListenerLookupType { // This is a container for V8EventListener objects that uses hidden properties of v8::Object to speed up lookups. class V8EventListenerList { public: - static PassRefPtr<V8EventListener> findWrapper(v8::Local<v8::Value> value, v8::Isolate* isolate) + static PassRefPtr<V8EventListener> findWrapper(v8::Local<v8::Value> value, ScriptState* scriptState) { - ASSERT(isolate->InContext()); + ASSERT(scriptState->isolate()->InContext()); if (!value->IsObject()) - return 0; + return nullptr; - v8::Handle<v8::String> wrapperProperty = getHiddenProperty(false, isolate); - return doFindWrapper(v8::Local<v8::Object>::Cast(value), wrapperProperty, isolate); + v8::Handle<v8::String> wrapperProperty = getHiddenProperty(false, scriptState->isolate()); + return doFindWrapper(v8::Local<v8::Object>::Cast(value), wrapperProperty, scriptState); } template<typename WrapperType> - static PassRefPtr<V8EventListener> findOrCreateWrapper(v8::Local<v8::Value>, bool isAttribute, v8::Isolate*); + static PassRefPtr<V8EventListener> findOrCreateWrapper(v8::Local<v8::Value>, bool isAttribute, ScriptState*); static void clearWrapper(v8::Handle<v8::Object> listenerObject, bool isAttribute, v8::Isolate* isolate) { @@ -68,13 +66,13 @@ public: listenerObject->DeleteHiddenValue(wrapperProperty); } - static PassRefPtr<EventListener> getEventListener(v8::Local<v8::Value>, bool isAttribute, ListenerLookupType); + static PassRefPtr<EventListener> getEventListener(ScriptState*, v8::Local<v8::Value>, bool isAttribute, ListenerLookupType); private: - static V8EventListener* doFindWrapper(v8::Local<v8::Object> object, v8::Handle<v8::String> wrapperProperty, v8::Isolate* isolate) + static V8EventListener* doFindWrapper(v8::Local<v8::Object> object, v8::Handle<v8::String> wrapperProperty, ScriptState* scriptState) { - ASSERT(isolate->InContext()); - v8::HandleScope scope(isolate); + v8::HandleScope scope(scriptState->isolate()); + ASSERT(scriptState->isolate()->InContext()); v8::Local<v8::Value> listener = object->GetHiddenValue(wrapperProperty); if (listener.IsEmpty()) return 0; @@ -83,27 +81,28 @@ private: static inline v8::Handle<v8::String> getHiddenProperty(bool isAttribute, v8::Isolate* isolate) { - return isAttribute ? V8HiddenPropertyName::attributeListener(isolate) : V8HiddenPropertyName::listener(isolate); + return isAttribute ? v8AtomicString(isolate, "attributeListener") : v8AtomicString(isolate, "listener"); } }; template<typename WrapperType> -PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(v8::Local<v8::Value> value, bool isAttribute, v8::Isolate* isolate) +PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(v8::Local<v8::Value> value, bool isAttribute, ScriptState* scriptState) { + v8::Isolate* isolate = scriptState->isolate(); ASSERT(isolate->InContext()); if (!value->IsObject() // Non-callable attribute setter input is treated as null (no wrapper) || (isAttribute && !value->IsFunction())) - return 0; + return nullptr; v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value); v8::Handle<v8::String> wrapperProperty = getHiddenProperty(isAttribute, isolate); - V8EventListener* wrapper = doFindWrapper(object, wrapperProperty, isolate); + V8EventListener* wrapper = doFindWrapper(object, wrapperProperty, scriptState); if (wrapper) return wrapper; - RefPtr<V8EventListener> wrapperPtr = WrapperType::create(object, isAttribute, isolate); + RefPtr<V8EventListener> wrapperPtr = WrapperType::create(object, isAttribute, scriptState); if (wrapperPtr) object->SetHiddenValue(wrapperProperty, v8::External::New(isolate, wrapperPtr.get())); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.cpp index 133914ad9c4..b09bfe742a3 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.cpp @@ -31,13 +31,12 @@ #include "config.h" #include "bindings/v8/V8GCController.h" -#include <algorithm> -#include "V8MutationObserver.h" -#include "V8Node.h" -#include "V8ScriptRunner.h" +#include "bindings/core/v8/V8MutationObserver.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/RetainedDOMInfo.h" #include "bindings/v8/V8AbstractEventListener.h" #include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8ScriptRunner.h" #include "bindings/v8/WrapperTypeInfo.h" #include "core/dom/Attr.h" #include "core/dom/NodeTraversal.h" @@ -46,8 +45,12 @@ #include "core/dom/shadow/ShadowRoot.h" #include "core/html/HTMLImageElement.h" #include "core/html/HTMLTemplateElement.h" +#include "core/html/imports/HTMLImportsController.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/svg/SVGElement.h" +#include "platform/Partitions.h" #include "platform/TraceEvent.h" +#include <algorithm> namespace WebCore { @@ -64,20 +67,23 @@ static void addReferencesForNodeWithEventListeners(v8::Isolate* isolate, Node* n if (!v8listener->hasExistingListenerObject()) continue; - // FIXME: update this to use the upcasting function which v8 will provide. - v8::Persistent<v8::Value>* value = reinterpret_cast<v8::Persistent<v8::Value>*>(&(v8listener->existingListenerObjectPersistentHandle())); - isolate->SetReference(wrapper, *value); + isolate->SetReference(wrapper, v8::Persistent<v8::Value>::Cast(v8listener->existingListenerObjectPersistentHandle())); } } Node* V8GCController::opaqueRootForGC(Node* node, v8::Isolate*) { + ASSERT(node); // FIXME: Remove the special handling for image elements. // The same special handling is in V8GCController::gcTree(). // Maybe should image elements be active DOM nodes? // See https://code.google.com/p/chromium/issues/detail?id=164882 - if (node->inDocument() || (node->hasTagName(HTMLNames::imgTag) && toHTMLImageElement(node)->hasPendingActivity())) - return &node->document(); + if (node->inDocument() || (isHTMLImageElement(*node) && toHTMLImageElement(*node).hasPendingActivity())) { + Document& document = node->document(); + if (HTMLImportsController* controller = document.importsController()) + return controller->master(); + return &document; + } if (node->isAttributeNode()) { Node* ownerElement = toAttr(node)->ownerElement(); @@ -117,12 +123,12 @@ public: if (m_nodesInNewSpace.size() >= wrappersHandledByEachMinorGC) return; - // Casting to a Handle is safe here, since the Persistent cannot get GCd + // Casting to a Handle is safe here, since the Persistent doesn't get GCd // during the GC prologue. ASSERT((*reinterpret_cast<v8::Handle<v8::Value>*>(value))->IsObject()); v8::Handle<v8::Object>* wrapper = reinterpret_cast<v8::Handle<v8::Object>*>(value); - ASSERT(V8DOMWrapper::maybeDOMWrapper(*wrapper)); - ASSERT(V8Node::hasInstanceInAnyWorld(*wrapper, m_isolate)); + ASSERT(V8DOMWrapper::isDOMWrapper(*wrapper)); + ASSERT(V8Node::hasInstance(*wrapper, m_isolate)); Node* node = V8Node::toNative(*wrapper); // A minor DOM GC can handle only node wrappers in the main world. // Note that node->wrapper().IsEmpty() returns true for nodes that @@ -132,8 +138,18 @@ public: ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(*wrapper); if (activeDOMObject && activeDOMObject->hasPendingActivity()) return; + // FIXME: Remove the special handling for image elements. + // The same special handling is in V8GCController::opaqueRootForGC(). + // Maybe should image elements be active DOM nodes? + // See https://code.google.com/p/chromium/issues/detail?id=164882 + if (isHTMLImageElement(*node) && toHTMLImageElement(*node).hasPendingActivity()) + return; + // FIXME: Remove the special handling for SVG context elements. + if (node->isSVGElement() && toSVGElement(node)->isContextElement()) + return; + m_nodesInNewSpace.append(node); - node->setV8CollectableDuringMinorGC(true); + node->markV8CollectableDuringMinorGC(); } } @@ -144,82 +160,83 @@ public: for (; nodeIterator < nodeIteratorEnd; ++nodeIterator) { Node* node = *nodeIterator; ASSERT(node->containsWrapper()); - if (node->isV8CollectableDuringMinorGC()) // This branch is just for performance. + if (node->isV8CollectableDuringMinorGC()) { // This branch is just for performance. gcTree(m_isolate, node); + node->clearV8CollectableDuringMinorGC(); + } } } private: - bool traverseTree(Node* rootNode, Vector<Node*, initialNodeVectorSize>* newSpaceNodes) + bool traverseTree(Node* rootNode, Vector<Node*, initialNodeVectorSize>* partiallyDependentNodes) { // To make each minor GC time bounded, we might need to give up // traversing at some point for a large DOM tree. That being said, // I could not observe the need even in pathological test cases. for (Node* node = rootNode; node; node = NodeTraversal::next(*node)) { if (node->containsWrapper()) { - // FIXME: Remove the special handling for image elements. - // FIXME: Remove the special handling for SVG context elements. - // The same special handling is in V8GCController::opaqueRootForGC(). - // Maybe should image elements be active DOM nodes? - // See https://code.google.com/p/chromium/issues/detail?id=164882 - if (!node->isV8CollectableDuringMinorGC() || (node->hasTagName(HTMLNames::imgTag) && toHTMLImageElement(node)->hasPendingActivity()) || (node->isSVGElement() && toSVGElement(node)->isContextElement())) { + if (!node->isV8CollectableDuringMinorGC()) { // This node is not in the new space of V8. This indicates that // the minor GC cannot anyway judge reachability of this DOM tree. // Thus we give up traversing the DOM tree. return false; } - node->setV8CollectableDuringMinorGC(false); - newSpaceNodes->append(node); + node->clearV8CollectableDuringMinorGC(); + partiallyDependentNodes->append(node); } if (ShadowRoot* shadowRoot = node->youngestShadowRoot()) { - if (!traverseTree(shadowRoot, newSpaceNodes)) + if (!traverseTree(shadowRoot, partiallyDependentNodes)) return false; } else if (node->isShadowRoot()) { if (ShadowRoot* shadowRoot = toShadowRoot(node)->olderShadowRoot()) { - if (!traverseTree(shadowRoot, newSpaceNodes)) + if (!traverseTree(shadowRoot, partiallyDependentNodes)) return false; } } // <template> has a |content| property holding a DOM fragment which we must traverse, // just like we do for the shadow trees above. - if (node->hasTagName(HTMLNames::templateTag)) { - if (!traverseTree(toHTMLTemplateElement(node)->content(), newSpaceNodes)) + if (isHTMLTemplateElement(*node)) { + if (!traverseTree(toHTMLTemplateElement(*node).content(), partiallyDependentNodes)) return false; } + + // Document maintains the list of imported documents through HTMLImportsController. + if (node->isDocumentNode()) { + Document* document = toDocument(node); + HTMLImportsController* controller = document->importsController(); + if (controller && document == controller->master()) { + for (unsigned i = 0; i < controller->loaderCount(); ++i) { + if (!traverseTree(controller->loaderDocumentAt(i), partiallyDependentNodes)) + return false; + } + } + } } return true; } void gcTree(v8::Isolate* isolate, Node* startNode) { - Vector<Node*, initialNodeVectorSize> newSpaceNodes; + Vector<Node*, initialNodeVectorSize> partiallyDependentNodes; Node* node = startNode; while (Node* parent = node->parentOrShadowHostOrTemplateHostNode()) node = parent; - if (!traverseTree(node, &newSpaceNodes)) + if (!traverseTree(node, &partiallyDependentNodes)) return; // We completed the DOM tree traversal. All wrappers in the DOM tree are - // stored in newSpaceNodes and are expected to exist in the new space of V8. + // stored in partiallyDependentNodes and are expected to exist in the new space of V8. // We report those wrappers to V8 as an object group. - Node** nodeIterator = newSpaceNodes.begin(); - Node** const nodeIteratorEnd = newSpaceNodes.end(); + Node** nodeIterator = partiallyDependentNodes.begin(); + Node** const nodeIteratorEnd = partiallyDependentNodes.end(); if (nodeIterator == nodeIteratorEnd) return; - v8::UniqueId id(reinterpret_cast<intptr_t>((*nodeIterator)->unsafePersistent().value())); + + Node* groupRoot = *nodeIterator; for (; nodeIterator != nodeIteratorEnd; ++nodeIterator) { - // This is safe because we know that GC won't happen before we - // dispose the UnsafePersistent (we're just preparing a GC). Though, - // we need to keep the UnsafePersistent alive until we're done with - // v8::Persistent. - UnsafePersistent<v8::Object> unsafeWrapper = (*nodeIterator)->unsafePersistent(); - v8::Persistent<v8::Object>* wrapper = unsafeWrapper.persistent(); - wrapper->MarkPartiallyDependent(); - // FIXME: update this to use the upcasting function which v8 will provide - v8::Persistent<v8::Value>* value = reinterpret_cast<v8::Persistent<v8::Value>*>(wrapper); - isolate->SetObjectGroupId(*value, id); + (*nodeIterator)->markAsDependentGroup(groupRoot, isolate); } } @@ -238,16 +255,14 @@ public: virtual void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) OVERRIDE { - // Casting to a Handle is safe here, since the Persistent cannot get GCd - // during the GC prologue. - ASSERT((*reinterpret_cast<v8::Handle<v8::Value>*>(value))->IsObject()); - if (classId != v8DOMNodeClassId && classId != v8DOMObjectClassId) return; + // Casting to a Handle is safe here, since the Persistent doesn't get GCd + // during the GC prologue. + ASSERT((*reinterpret_cast<v8::Handle<v8::Value>*>(value))->IsObject()); v8::Handle<v8::Object>* wrapper = reinterpret_cast<v8::Handle<v8::Object>*>(value); - - ASSERT(V8DOMWrapper::maybeDOMWrapper(*wrapper)); + ASSERT(V8DOMWrapper::isDOMWrapper(*wrapper)); if (value->IsIndependent()) return; @@ -255,26 +270,13 @@ public: const WrapperTypeInfo* type = toWrapperTypeInfo(*wrapper); void* object = toNative(*wrapper); - if (V8MutationObserver::wrapperTypeInfo.equals(type)) { - // FIXME: Allow opaqueRootForGC to operate on multiple roots and move this logic into V8MutationObserverCustom. - MutationObserver* observer = static_cast<MutationObserver*>(object); - HashSet<Node*> observedNodes = observer->getObservedNodes(); - for (HashSet<Node*>::iterator it = observedNodes.begin(); it != observedNodes.end(); ++it) { - v8::UniqueId id(reinterpret_cast<intptr_t>(V8GCController::opaqueRootForGC(*it, m_isolate))); - m_isolate->SetReferenceFromGroup(id, *value); - } - } else { - ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(*wrapper); - if (activeDOMObject && activeDOMObject->hasPendingActivity()) - m_isolate->SetObjectGroupId(*value, liveRootId()); - } + ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(*wrapper); + if (activeDOMObject && activeDOMObject->hasPendingActivity()) + m_isolate->SetObjectGroupId(*value, liveRootId()); if (classId == v8DOMNodeClassId) { - ASSERT(V8Node::hasInstanceInAnyWorld(*wrapper, m_isolate)); - ASSERT(!value->IsIndependent()); - + ASSERT(V8Node::hasInstance(*wrapper, m_isolate)); Node* node = static_cast<Node*>(object); - if (node->hasEventListeners()) addReferencesForNodeWithEventListeners(m_isolate, node, v8::Persistent<v8::Object>::Cast(*value)); Node* root = V8GCController::opaqueRootForGC(node, m_isolate); @@ -282,9 +284,7 @@ public: if (m_constructRetainedObjectInfos) m_groupsWhichNeedRetainerInfo.append(root); } else if (classId == v8DOMObjectClassId) { - ASSERT(!value->IsIndependent()); - v8::Persistent<v8::Object>* wrapperPersistent = reinterpret_cast<v8::Persistent<v8::Object>*>(value); - type->visitDOMWrapper(object, *wrapperPersistent, m_isolate); + type->visitDOMWrapper(object, v8::Persistent<v8::Object>::Cast(*value), m_isolate); } else { ASSERT_NOT_REACHED(); } @@ -325,10 +325,18 @@ private: bool m_constructRetainedObjectInfos; }; +static unsigned long long usedHeapSize(v8::Isolate* isolate) +{ + v8::HeapStatistics heapStatistics; + isolate->GetHeapStatistics(&heapStatistics); + return heapStatistics.used_heap_size(); +} + void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags) { // FIXME: It would be nice if the GC callbacks passed the Isolate directly.... v8::Isolate* isolate = v8::Isolate::GetCurrent(); + TRACE_EVENT_BEGIN1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "GCEvent", "usedHeapSizeBefore", usedHeapSize(isolate)); if (type == v8::kGCTypeScavenge) minorGCPrologue(isolate); else if (type == v8::kGCTypeMarkSweepCompact) @@ -340,14 +348,14 @@ void V8GCController::minorGCPrologue(v8::Isolate* isolate) TRACE_EVENT_BEGIN0("v8", "minorGC"); if (isMainThread()) { { - TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "MinorGC"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMMinorGC"); v8::HandleScope scope(isolate); MinorGCWrapperVisitor visitor(isolate); v8::V8::VisitHandlesForPartialDependence(isolate, &visitor); visitor.notifyFinished(); } V8PerIsolateData::from(isolate)->setPreviousSamplingState(TRACE_EVENT_GET_SAMPLING_STATE()); - TRACE_EVENT_SET_SAMPLING_STATE("V8", "MinorGC"); + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8MinorGC"); } } @@ -358,13 +366,13 @@ void V8GCController::majorGCPrologue(bool constructRetainedObjectInfos, v8::Isol TRACE_EVENT_BEGIN0("v8", "majorGC"); if (isMainThread()) { { - TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "MajorGC"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMMajorGC"); MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos); v8::V8::VisitHandlesWithClassIds(&visitor); visitor.notifyFinished(); } V8PerIsolateData::from(isolate)->setPreviousSamplingState(TRACE_EVENT_GET_SAMPLING_STATE()); - TRACE_EVENT_SET_SAMPLING_STATE("V8", "MajorGC"); + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8MajorGC"); } else { MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos); v8::V8::VisitHandlesWithClassIds(&visitor); @@ -380,6 +388,29 @@ void V8GCController::gcEpilogue(v8::GCType type, v8::GCCallbackFlags flags) minorGCEpilogue(isolate); else if (type == v8::kGCTypeMarkSweepCompact) majorGCEpilogue(isolate); + + // Forces a Blink heap garbage collection when a garbage collection + // was forced from V8. This is used for tests that force GCs from + // JavaScript to verify that objects die when expected. + if (flags & v8::kGCCallbackFlagForced) { + // This single GC is not enough for two reasons: + // (1) The GC is not precise because the GC scans on-stack pointers conservatively. + // (2) One GC is not enough to break a chain of persistent handles. It's possible that + // some heap allocated objects own objects that contain persistent handles + // pointing to other heap allocated objects. To break the chain, we need multiple GCs. + // + // Regarding (1), we force a precise GC at the end of the current event loop. So if you want + // to collect all garbage, you need to wait until the next event loop. + // Regarding (2), it would be OK in practice to trigger only one GC per gcEpilogue, because + // GCController.collectAll() forces 7 V8's GC. + Heap::collectGarbage(ThreadState::HeapPointersOnStack); + + // Forces a precise GC at the end of the current event loop. + Heap::setForcePreciseGCForTesting(); + } + + TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "GCEvent", "usedHeapSizeAfter", usedHeapSize(isolate)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); } void V8GCController::minorGCEpilogue(v8::Isolate* isolate) @@ -398,25 +429,27 @@ void V8GCController::majorGCEpilogue(v8::Isolate* isolate) TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState()); } -void V8GCController::hintForCollectGarbage() +void V8GCController::collectGarbage(v8::Isolate* isolate) { - V8PerIsolateData* data = V8PerIsolateData::current(); - if (!data->shouldCollectGarbageSoon()) - return; - const int longIdlePauseInMS = 1000; - data->clearShouldCollectGarbageSoon(); - v8::V8::ContextDisposedNotification(); - v8::V8::IdleNotification(longIdlePauseInMS); + v8::HandleScope handleScope(isolate); + RefPtr<ScriptState> scriptState = ScriptState::create(v8::Context::New(isolate), DOMWrapperWorld::create()); + ScriptState::Scope scope(scriptState.get()); + V8ScriptRunner::compileAndRunInternalScript(v8String(isolate, "if (gc) gc();"), isolate); + scriptState->disposePerContextData(); } -void V8GCController::collectGarbage(v8::Isolate* isolate) +void V8GCController::reportDOMMemoryUsageToV8(v8::Isolate* isolate) { - v8::HandleScope handleScope(isolate); - v8::Local<v8::Context> context = v8::Context::New(isolate); - if (context.IsEmpty()) + if (!isMainThread()) return; - v8::Context::Scope contextScope(context); - V8ScriptRunner::compileAndRunInternalScript(v8String(isolate, "if (gc) gc();"), isolate); + + static size_t lastUsageReportedToV8 = 0; + + size_t currentUsage = Partitions::currentDOMMemoryUsage(); + int64_t diff = static_cast<int64_t>(currentUsage) - static_cast<int64_t>(lastUsageReportedToV8); + isolate->AdjustAmountOfExternalAllocatedMemory(diff); + + lastUsageReportedToV8 = currentUsage; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.h b/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.h index b0aa80227d5..b0c541a84b5 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.h @@ -47,10 +47,11 @@ public: static void majorGCPrologue(bool constructRetainedObjectInfos, v8::Isolate*); static void majorGCEpilogue(v8::Isolate*); - static void hintForCollectGarbage(); static void collectGarbage(v8::Isolate*); static Node* opaqueRootForGC(Node*, v8::Isolate*); + + static void reportDOMMemoryUsageToV8(v8::Isolate*); }; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.cpp index e7d40bd129e..688a212a30c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.cpp @@ -32,6 +32,7 @@ #include "bindings/v8/V8GCForContextDispose.h" #include "wtf/StdLibExtras.h" +#include <v8.h> namespace WebCore { @@ -46,7 +47,7 @@ void V8GCForContextDispose::notifyContextDisposed(bool isMainFrame) m_didDisposeContextForMainFrame = m_didDisposeContextForMainFrame || isMainFrame; v8::V8::ContextDisposedNotification(); if (!m_pseudoIdleTimer.isActive()) - m_pseudoIdleTimer.startOneShot(0.8); + m_pseudoIdleTimer.startOneShot(0.8, FROM_HERE); } void V8GCForContextDispose::notifyIdleSooner(double maximumFireInterval) @@ -55,7 +56,7 @@ void V8GCForContextDispose::notifyIdleSooner(double maximumFireInterval) double nextFireInterval = m_pseudoIdleTimer.nextFireInterval(); if (nextFireInterval > maximumFireInterval) { m_pseudoIdleTimer.stop(); - m_pseudoIdleTimer.startOneShot(maximumFireInterval); + m_pseudoIdleTimer.startOneShot(maximumFireInterval, FROM_HERE); } } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.h b/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.h index 3d16be47de2..53fbbfd53e3 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.h @@ -31,7 +31,6 @@ #ifndef V8GCForContextDispose_h #define V8GCForContextDispose_h -#include <v8.h> #include "platform/Timer.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptObject.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8GarbageCollected.h index 36b1a54451a..697974839d9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptObject.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8GarbageCollected.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2014 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,55 +28,62 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "bindings/v8/ScriptObject.h" - -#include "bindings/v8/ScriptScope.h" -#include "bindings/v8/ScriptState.h" - -#include "V8InspectorFrontendHost.h" +#ifndef V8GarbageCollected_h +#define V8GarbageCollected_h #include <v8.h> namespace WebCore { -ScriptObject::ScriptObject(ScriptState* scriptState, v8::Handle<v8::Object> v8Object) - : ScriptValue(v8Object, scriptState->isolate()) - , m_scriptState(scriptState) -{ -} +template<typename T> +class V8GarbageCollected { + WTF_MAKE_NONCOPYABLE(V8GarbageCollected); +public: + static T* Cast(v8::Handle<v8::Value> value) + { + ASSERT(value->IsExternal()); + T* result = static_cast<T*>(value.As<v8::External>()->Value()); + RELEASE_ASSERT(result->m_handle == value); + return result; + } -ScriptObject::ScriptObject(ScriptState* scriptState, const ScriptValue& scriptValue) - : ScriptValue(scriptValue) - , m_scriptState(scriptState) -{ -} +protected: + V8GarbageCollected(v8::Isolate* isolate) + : m_isolate(isolate) + , m_handle(isolate, v8::External::New(isolate, static_cast<T*>(this))) + , m_releasedToV8GarbageCollector(false) + { + } -v8::Handle<v8::Object> ScriptObject::v8Object() const -{ - ASSERT(v8Value()->IsObject()); - return v8::Handle<v8::Object>::Cast(v8Value()); -} + v8::Handle<v8::External> releaseToV8GarbageCollector() + { + ASSERT(!m_handle.isWeak()); // Call this exactly once. + m_releasedToV8GarbageCollector = true; + v8::Handle<v8::External> result = m_handle.newLocal(m_isolate); + m_handle.setWeak(static_cast<T*>(this), &weakCallback); + return result; + } -bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InspectorFrontendHost* value) -{ - ScriptScope scope(scriptState); - scope.global()->Set(v8AtomicString(scriptState->isolate(), name), toV8(value, v8::Handle<v8::Object>(), scriptState->isolate())); - return scope.success(); -} + ~V8GarbageCollected() + { + ASSERT(!m_releasedToV8GarbageCollector || m_handle.isEmpty()); + } -bool ScriptGlobalObject::get(ScriptState* scriptState, const char* name, ScriptObject& value) -{ - ScriptScope scope(scriptState); - v8::Local<v8::Value> v8Value = scope.global()->Get(v8AtomicString(scriptState->isolate(), name)); - if (v8Value.IsEmpty()) - return false; + v8::Isolate* isolate() { return m_isolate; } - if (!v8Value->IsObject()) - return false; +private: + static void weakCallback(const v8::WeakCallbackData<v8::External, T>& data) + { + T* self = data.GetParameter(); + self->m_handle.clear(); + delete self; + } - value = ScriptObject(scriptState, v8::Handle<v8::Object>::Cast(v8Value)); - return true; -} + v8::Isolate* m_isolate; + ScopedPersistent<v8::External> m_handle; + bool m_releasedToV8GarbageCollector; +}; } // namespace WebCore + +#endif // V8GarbageCollected_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.cpp deleted file mode 100644 index 1108e9e7aa0..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "bindings/v8/V8HiddenPropertyName.h" - -#include "bindings/v8/V8Binding.h" -#include <string.h> -#include "wtf/StdLibExtras.h" -#include "wtf/Vector.h" - -namespace WebCore { - -#define V8_AS_STRING(x) V8_AS_STRING_IMPL(x) -#define V8_AS_STRING_IMPL(x) #x - -#define V8_HIDDEN_PROPERTY_PREFIX "WebCore::HiddenProperty::" - -#define V8_DEFINE_HIDDEN_PROPERTY(name) \ -v8::Handle<v8::String> V8HiddenPropertyName::name(v8::Isolate* isolate) \ -{ \ - V8HiddenPropertyName* hiddenPropertyName = V8PerIsolateData::from(isolate)->hiddenPropertyName(); \ - if (hiddenPropertyName->m_##name.IsEmpty()) { \ - createString(V8_HIDDEN_PROPERTY_PREFIX V8_AS_STRING(name), &(hiddenPropertyName->m_##name), isolate); \ - } \ - return v8::Local<v8::String>::New(isolate, hiddenPropertyName->m_##name); \ -} - -V8_HIDDEN_PROPERTIES(V8_DEFINE_HIDDEN_PROPERTY); - -static v8::Handle<v8::String> hiddenReferenceName(const char* name, unsigned length) -{ - ASSERT(length); - Vector<char, 64> prefixedName; - prefixedName.append(V8_HIDDEN_PROPERTY_PREFIX, sizeof(V8_HIDDEN_PROPERTY_PREFIX) - 1); - prefixedName.append(name, length); - return v8AtomicString(v8::Isolate::GetCurrent(), prefixedName.data(), static_cast<int>(prefixedName.size())); -} - -void V8HiddenPropertyName::setNamedHiddenReference(v8::Handle<v8::Object> parent, const char* name, v8::Handle<v8::Value> child) -{ - ASSERT(name); - parent->SetHiddenValue(hiddenReferenceName(name, strlen(name)), child); -} - -void V8HiddenPropertyName::createString(const char* key, v8::Persistent<v8::String>* handle, v8::Isolate* isolate) -{ - v8::HandleScope scope(isolate); - handle->Reset(isolate, v8AtomicString(isolate, key)); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.h b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.h deleted file mode 100644 index 76dc17ca1ae..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef V8HiddenPropertyName_h -#define V8HiddenPropertyName_h - -#include <v8.h> - -namespace WebCore { - -#define V8_HIDDEN_PROPERTIES(V) \ - V(adaptorFunctionPeer) \ - V(attributeListener) \ - V(callback) \ - V(condition) \ - V(customElementAttached) \ - V(customElementAttributeChanged) \ - V(customElementCreated) \ - V(customElementDetached) \ - V(customElementDocument) \ - V(customElementIsInterfacePrototypeObject) \ - V(customElementNamespaceURI) \ - V(customElementTagName) \ - V(customElementType) \ - V(data) \ - V(detail) \ - V(document) \ - V(event) \ - V(error) \ - V(listener) \ - V(scriptState) \ - V(sleepFunction) \ - V(state) \ - V(toStringString) \ - V(typedArrayHiddenCopyMethod) \ - V(thenableHiddenPromise) - -class V8HiddenPropertyName { -public: - V8HiddenPropertyName() { } -#define V8_DECLARE_PROPERTY(name) static v8::Handle<v8::String> name(v8::Isolate*); - V8_HIDDEN_PROPERTIES(V8_DECLARE_PROPERTY); -#undef V8_DECLARE_PROPERTY - - static void setNamedHiddenReference(v8::Handle<v8::Object> parent, const char* name, v8::Handle<v8::Value> child); - -private: - static void createString(const char* key, v8::Persistent<v8::String>* handle, v8::Isolate*); -#define V8_DECLARE_FIELD(name) v8::Persistent<v8::String> m_##name; - V8_HIDDEN_PROPERTIES(V8_DECLARE_FIELD); -#undef V8_DECLARE_FIELD -}; - -} - -#endif // V8HiddenPropertyName_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.cpp new file mode 100644 index 00000000000..ab6e97d147c --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.cpp @@ -0,0 +1,46 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/v8/V8HiddenValue.h" + +#include "bindings/v8/ScriptWrappable.h" +#include "bindings/v8/V8Binding.h" + +namespace WebCore { + +#define V8_DEFINE_METHOD(name) \ +v8::Handle<v8::String> V8HiddenValue::name(v8::Isolate* isolate) \ +{ \ + V8HiddenValue* hiddenValue = V8PerIsolateData::from(isolate)->hiddenValue(); \ + if (hiddenValue->m_##name.isEmpty()) { \ + hiddenValue->m_##name.set(isolate, v8AtomicString(isolate, #name)); \ + } \ + return hiddenValue->m_##name.newLocal(isolate); \ +} + +V8_HIDDEN_VALUES(V8_DEFINE_METHOD); + +v8::Local<v8::Value> V8HiddenValue::getHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, v8::Handle<v8::String> key) +{ + return object->GetHiddenValue(key); +} + +bool V8HiddenValue::setHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, v8::Handle<v8::String> key, v8::Handle<v8::Value> value) +{ + return object->SetHiddenValue(key, value); +} + +bool V8HiddenValue::deleteHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, v8::Handle<v8::String> key) +{ + return object->DeleteHiddenValue(key); +} + +v8::Local<v8::Value> V8HiddenValue::getHiddenValueFromMainWorldWrapper(v8::Isolate* isolate, ScriptWrappable* wrappable, v8::Handle<v8::String> key) +{ + v8::Local<v8::Object> wrapper = wrappable->newLocalWrapper(isolate); + return wrapper.IsEmpty() ? v8::Local<v8::Value>() : getHiddenValue(isolate, wrapper, key); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.h b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.h new file mode 100644 index 00000000000..75da4efe761 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.h @@ -0,0 +1,61 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8HiddenValue_h +#define V8HiddenValue_h + +#include "bindings/v8/ScopedPersistent.h" +#include <v8.h> + +namespace WebCore { + +class ScriptWrappable; + +#define V8_HIDDEN_VALUES(V) \ + V(arrayBufferData) \ + V(customElementAttached) \ + V(customElementAttributeChanged) \ + V(customElementCreated) \ + V(customElementDetached) \ + V(customElementDocument) \ + V(customElementIsInterfacePrototypeObject) \ + V(customElementNamespaceURI) \ + V(customElementTagName) \ + V(customElementType) \ + V(callback) \ + V(condition) \ + V(data) \ + V(detail) \ + V(document) \ + V(error) \ + V(event) \ + V(idbCursorRequest) \ + V(port1) \ + V(port2) \ + V(state) \ + V(stringData) \ + V(scriptState) \ + V(thenableHiddenPromise) \ + V(toStringString) + +class V8HiddenValue { +public: +#define V8_DECLARE_METHOD(name) static v8::Handle<v8::String> name(v8::Isolate* isolate); + V8_HIDDEN_VALUES(V8_DECLARE_METHOD); +#undef V8_DECLARE_METHOD + + static v8::Local<v8::Value> getHiddenValue(v8::Isolate*, v8::Handle<v8::Object>, v8::Handle<v8::String>); + static bool setHiddenValue(v8::Isolate*, v8::Handle<v8::Object>, v8::Handle<v8::String>, v8::Handle<v8::Value>); + static bool deleteHiddenValue(v8::Isolate*, v8::Handle<v8::Object>, v8::Handle<v8::String>); + static v8::Local<v8::Value> getHiddenValueFromMainWorldWrapper(v8::Isolate*, ScriptWrappable*, v8::Handle<v8::String>); + +private: +#define V8_DECLARE_FIELD(name) ScopedPersistent<v8::String> m_##name; + V8_HIDDEN_VALUES(V8_DECLARE_FIELD); +#undef V8_DECLARE_FIELD +}; + +} // namespace WebCore + +#endif // V8HiddenValue_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Initializer.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8Initializer.cpp index 9646ae76204..0f2f1f13261 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Initializer.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8Initializer.cpp @@ -26,11 +26,11 @@ #include "config.h" #include "bindings/v8/V8Initializer.h" -#include "V8DOMException.h" -#include "V8ErrorEvent.h" -#include "V8History.h" -#include "V8Location.h" -#include "V8Window.h" +#include "bindings/core/v8/V8DOMException.h" +#include "bindings/core/v8/V8ErrorEvent.h" +#include "bindings/core/v8/V8History.h" +#include "bindings/core/v8/V8Location.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScriptCallStackFactory.h" #include "bindings/v8/ScriptController.h" @@ -38,15 +38,15 @@ #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ErrorHandler.h" #include "bindings/v8/V8GCController.h" -#include "bindings/v8/V8HiddenPropertyName.h" #include "bindings/v8/V8PerContextData.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" -#include "core/inspector/ScriptCallStack.h" #include "core/frame/ConsoleTypes.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "core/inspector/ScriptCallStack.h" +#include "platform/TraceEvent.h" #include "public/platform/Platform.h" #include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" @@ -54,12 +54,12 @@ namespace WebCore { -static Frame* findFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data, v8::Isolate* isolate) +static LocalFrame* findFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data, v8::Isolate* isolate) { const WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data); if (V8Window::wrapperTypeInfo.equals(type)) { - v8::Handle<v8::Object> windowWrapper = host->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldTypeInMainThread(isolate))); + v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(host, isolate); if (windowWrapper.IsEmpty()) return 0; return V8Window::toNative(windowWrapper)->frame(); @@ -85,30 +85,34 @@ static void reportFatalErrorInMainThread(const char* location, const char* messa static void messageHandlerInMainThread(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - // If called during context initialization, there will be no entered context. - v8::Handle<v8::Context> enteredContext = isolate->GetEnteredContext(); - if (enteredContext.IsEmpty()) + ASSERT(isMainThread()); + // It's possible that messageHandlerInMainThread() is invoked while we're initializing a window. + // In that half-baked situation, we don't have a valid context nor a valid world, + // so just return immediately. + if (DOMWrapperWorld::windowIsBeingInitialized()) return; - DOMWindow* firstWindow = toDOMWindow(enteredContext); - if (!firstWindow->isCurrentlyDisplayedInFrame()) + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + // If called during context initialization, there will be no entered window. + LocalDOMWindow* enteredWindow = enteredDOMWindow(isolate); + if (!enteredWindow || !enteredWindow->isCurrentlyDisplayedInFrame()) return; String errorMessage = toCoreString(message->Get()); v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace(); - RefPtr<ScriptCallStack> callStack; + RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; // Currently stack trace is only collected when inspector is open. if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) callStack = createScriptCallStack(stackTrace, ScriptCallStack::maxCallStackSizeToCapture, isolate); v8::Handle<v8::Value> resourceName = message->GetScriptResourceName(); bool shouldUseDocumentURL = resourceName.IsEmpty() || !resourceName->IsString(); - String resource = shouldUseDocumentURL ? firstWindow->document()->url() : toCoreString(resourceName.As<v8::String>()); + String resource = shouldUseDocumentURL ? enteredWindow->document()->url() : toCoreString(resourceName.As<v8::String>()); AccessControlStatus corsStatus = message->IsSharedCrossOrigin() ? SharableCrossOrigin : NotSharableCrossOrigin; - RefPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, resource, message->GetLineNumber(), message->GetStartColumn() + 1, DOMWrapperWorld::current()); + ScriptState* scriptState = ScriptState::current(isolate); + RefPtrWillBeRawPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, resource, message->GetLineNumber(), message->GetStartColumn() + 1, &scriptState->world()); if (V8DOMWrapper::isDOMWrapper(data)) { v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(data); const WrapperTypeInfo* type = toWrapperTypeInfo(obj); @@ -122,22 +126,24 @@ static void messageHandlerInMainThread(v8::Handle<v8::Message> message, v8::Hand // This method might be called while we're creating a new context. In this case, we // avoid storing the exception object, as we can't create a wrapper during context creation. // FIXME: Can we even get here during initialization now that we bail out when GetEntered returns an empty handle? - DOMWrapperWorld* world = DOMWrapperWorld::current(); - Frame* frame = firstWindow->document()->frame(); - if (world && frame && frame->script().existingWindowShell(world)) - V8ErrorHandler::storeExceptionOnErrorEventWrapper(event.get(), data, v8::Isolate::GetCurrent()); - firstWindow->document()->reportException(event.release(), callStack, corsStatus); + LocalFrame* frame = enteredWindow->document()->frame(); + if (frame && frame->script().existingWindowShell(scriptState->world())) { + V8ErrorHandler::storeExceptionOnErrorEventWrapper(event.get(), data, scriptState->context()->Global(), isolate); + } + enteredWindow->document()->reportException(event.release(), callStack, corsStatus); } static void failedAccessCheckCallbackInMainThread(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data) { - Frame* target = findFrame(host, data, v8::Isolate::GetCurrent()); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + LocalFrame* target = findFrame(host, data, isolate); if (!target) return; - DOMWindow* targetWindow = target->domWindow(); + LocalDOMWindow* targetWindow = target->domWindow(); - ExceptionState exceptionState(v8::Handle<v8::Object>(), v8::Isolate::GetCurrent()); - exceptionState.throwSecurityError(targetWindow->sanitizedCrossDomainAccessErrorMessage(activeDOMWindow()), targetWindow->crossDomainAccessErrorMessage(activeDOMWindow())); + // FIXME: We should modify V8 to pass in more contextual information (context, property, and object). + ExceptionState exceptionState(ExceptionState::UnknownContext, 0, 0, isolate->GetCurrentContext()->Global(), isolate); + exceptionState.throwSecurityError(targetWindow->sanitizedCrossDomainAccessErrorMessage(callingDOMWindow(isolate)), targetWindow->crossDomainAccessErrorMessage(callingDOMWindow(isolate))); exceptionState.throwIfNeeded(); } @@ -145,22 +151,32 @@ static bool codeGenerationCheckCallbackInMainThread(v8::Local<v8::Context> conte { if (ExecutionContext* executionContext = toExecutionContext(context)) { if (ContentSecurityPolicy* policy = toDocument(executionContext)->contentSecurityPolicy()) - return policy->allowEval(ScriptState::forContext(context)); + return policy->allowEval(ScriptState::from(context)); } return false; } +static void timerTraceProfilerInMainThread(const char* name, int status) +{ + if (!status) { + TRACE_EVENT_BEGIN0("V8", name); + } else { + TRACE_EVENT_END0("V8", name); + } +} + static void initializeV8Common(v8::Isolate* isolate) { v8::ResourceConstraints constraints; - constraints.ConfigureDefaults(static_cast<uint64_t>(blink::Platform::current()->physicalMemoryMB()) << 20, static_cast<uint32_t>(blink::Platform::current()->numberOfProcessors())); + constraints.ConfigureDefaults(static_cast<uint64_t>(blink::Platform::current()->physicalMemoryMB()) << 20, static_cast<uint32_t>(blink::Platform::current()->virtualMemoryLimitMB()) << 20, static_cast<uint32_t>(blink::Platform::current()->numberOfProcessors())); v8::SetResourceConstraints(isolate, &constraints); v8::V8::AddGCPrologueCallback(V8GCController::gcPrologue); v8::V8::AddGCEpilogueCallback(V8GCController::gcEpilogue); - v8::V8::IgnoreOutOfMemoryException(); - v8::Debug::SetLiveEditEnabled(false); + v8::Debug::SetLiveEditEnabled(isolate, false); + + isolate->SetAutorunMicrotasks(false); } void V8Initializer::initializeMainThreadIfNeeded(v8::Isolate* isolate) @@ -175,11 +191,14 @@ void V8Initializer::initializeMainThreadIfNeeded(v8::Isolate* isolate) initializeV8Common(isolate); v8::V8::SetFatalErrorHandler(reportFatalErrorInMainThread); + V8PerIsolateData::ensureInitialized(isolate); v8::V8::AddMessageListener(messageHandlerInMainThread); v8::V8::SetFailedAccessCheckCallbackFunction(failedAccessCheckCallbackInMainThread); v8::V8::SetAllowCodeGenerationFromStringsCallback(codeGenerationCheckCallbackInMainThread); + + isolate->SetEventLogger(timerTraceProfilerInMainThread); + ScriptProfiler::initialize(); - V8PerIsolateData::ensureInitialized(isolate); } static void reportFatalErrorInWorker(const char* location, const char* message) @@ -197,16 +216,18 @@ static void messageHandlerInWorker(v8::Handle<v8::Message> message, v8::Handle<v return; isReportingException = true; + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + ScriptState* scriptState = ScriptState::current(isolate); // During the frame teardown, there may not be a valid context. - if (ExecutionContext* context = getExecutionContext()) { + if (ExecutionContext* context = scriptState->executionContext()) { String errorMessage = toCoreString(message->Get()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, sourceURL, message->GetScriptResourceName()); + TOSTRING_VOID(V8StringResource<>, sourceURL, message->GetScriptResourceName()); - RefPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, sourceURL, message->GetLineNumber(), message->GetStartColumn() + 1, DOMWrapperWorld::current()); + RefPtrWillBeRawPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, sourceURL, message->GetLineNumber(), message->GetStartColumn() + 1, &DOMWrapperWorld::current(isolate)); AccessControlStatus corsStatus = message->IsSharedCrossOrigin() ? SharableCrossOrigin : NotSharableCrossOrigin; - V8ErrorHandler::storeExceptionOnErrorEventWrapper(event.get(), data, v8::Isolate::GetCurrent()); - context->reportException(event.release(), 0, corsStatus); + V8ErrorHandler::storeExceptionOnErrorEventWrapper(event.get(), data, scriptState->context()->Global(), isolate); + context->reportException(event.release(), nullptr, corsStatus); } isReportingException = false; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.cpp index 1d80ffd89bf..23b8fcf52f8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.cpp @@ -31,29 +31,29 @@ #include "config.h" #include "bindings/v8/V8LazyEventListener.h" -#include "V8Document.h" -#include "V8HTMLFormElement.h" -#include "V8Node.h" +#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8HTMLFormElement.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/ScriptSourceCode.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8ScriptRunner.h" #include "core/dom/Document.h" #include "core/dom/Node.h" #include "core/html/HTMLElement.h" #include "core/html/HTMLFormElement.h" #include "core/inspector/InspectorInstrumentation.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "wtf/StdLibExtras.h" namespace WebCore { V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String sourceURL, const TextPosition& position, Node* node, v8::Isolate* isolate) - : V8AbstractEventListener(true, mainThreadNormalWorld(), isolate) + : V8AbstractEventListener(true, isolate) , m_functionName(functionName) , m_eventParameterName(eventParameterName) , m_code(code) @@ -64,35 +64,31 @@ V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const } template<typename T> -v8::Handle<v8::Object> toObjectWrapper(T* domObject, v8::Isolate* isolate) +v8::Handle<v8::Object> toObjectWrapper(T* domObject, ScriptState* scriptState) { if (!domObject) - return v8::Object::New(); - v8::Handle<v8::Value> value = toV8(domObject, v8::Handle<v8::Object>(), isolate); + return v8::Object::New(scriptState->isolate()); + v8::Handle<v8::Value> value = toV8(domObject, scriptState->context()->Global(), scriptState->isolate()); if (value.IsEmpty()) - return v8::Object::New(); - return v8::Local<v8::Object>::New(isolate, value.As<v8::Object>()); + return v8::Object::New(scriptState->isolate()); + return v8::Local<v8::Object>::New(scriptState->isolate(), value.As<v8::Object>()); } -v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) +v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { - v8::Local<v8::Object> listenerObject = getListenerObject(context); + v8::Local<v8::Object> listenerObject = getListenerObject(scriptState()->executionContext()); if (listenerObject.IsEmpty()) return v8::Local<v8::Value>(); v8::Local<v8::Function> handlerFunction = listenerObject.As<v8::Function>(); - v8::Local<v8::Object> receiver = getReceiverObject(context, event); + v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); - // FIXME: Can |context| be 0 here? - if (!context) + if (!scriptState()->executionContext()->isDocument()) return v8::Local<v8::Value>(); - if (!context->isDocument()) - return v8::Local<v8::Value>(); - - Frame* frame = toDocument(context)->frame(); + LocalFrame* frame = toDocument(scriptState()->executionContext())->frame(); if (!frame) return v8::Local<v8::Value>(); @@ -105,11 +101,32 @@ v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ExecutionContext* static void V8LazyEventListenerToString(const v8::FunctionCallbackInfo<v8::Value>& info) { - v8SetReturnValue(info, info.Holder()->GetHiddenValue(V8HiddenPropertyName::toStringString(info.GetIsolate()))); + v8SetReturnValue(info, V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::toStringString(info.GetIsolate()))); +} + +void V8LazyEventListener::handleEvent(ExecutionContext* context, Event* event) +{ + v8::HandleScope handleScope(toIsolate(context)); + // V8LazyEventListener doesn't know the associated context when created. + // Thus we lazily get the associated context and set a ScriptState on V8AbstractEventListener. + v8::Local<v8::Context> v8Context = toV8Context(context, world()); + if (v8Context.IsEmpty()) + return; + setScriptState(ScriptState::from(v8Context)); + + V8AbstractEventListener::handleEvent(context, event); } void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) { + v8::HandleScope handleScope(toIsolate(context)); + // V8LazyEventListener doesn't know the associated context when created. + // Thus we lazily get the associated context and set a ScriptState on V8AbstractEventListener. + v8::Local<v8::Context> v8Context = toV8Context(context, world()); + if (v8Context.IsEmpty()) + return; + setScriptState(ScriptState::from(v8Context)); + if (context->isDocument() && !toDocument(context)->allowInlineEventHandlers(m_node, this, m_sourceURL, m_position.m_line)) { clearListenerObject(); return; @@ -120,17 +137,7 @@ void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) ASSERT(context->isDocument()); - v8::Isolate* isolate = toIsolate(context); - v8::HandleScope handleScope(isolate); - - // Use the outer scope to hold context. - v8::Local<v8::Context> v8Context = toV8Context(context, world()); - // Bail out if we cannot get the context. - if (v8Context.IsEmpty()) - return; - - v8::Context::Scope scope(v8Context); - + ScriptState::Scope scope(scriptState()); String listenerSource = InspectorInstrumentation::preprocessEventListener(toDocument(context)->frame(), m_code, m_sourceURL, m_functionName); // FIXME: Remove the following 'with' hack. @@ -159,9 +166,9 @@ void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) "};" "}}}})"; - v8::Handle<v8::String> codeExternalString = v8String(isolate, code); + v8::Handle<v8::String> codeExternalString = v8String(isolate(), code); - v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(codeExternalString, isolate, m_sourceURL, m_position, 0); + v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(codeExternalString, isolate(), m_sourceURL, m_position); if (result.IsEmpty()) return; @@ -173,22 +180,22 @@ void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) if (m_node && m_node->isHTMLElement()) formElement = toHTMLElement(m_node)->formOwner(); - v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, isolate); - v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formElement, isolate); - v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0, isolate); + v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, scriptState()); + v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formElement, scriptState()); + v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0, scriptState()); - v8::Local<v8::Object> thisObject = v8::Object::New(); + v8::Local<v8::Object> thisObject = v8::Object::New(isolate()); if (thisObject.IsEmpty()) return; - if (!thisObject->ForceSet(v8::Integer::New(0, isolate), nodeWrapper)) + if (!thisObject->ForceSet(v8::Integer::New(isolate(), 0), nodeWrapper)) return; - if (!thisObject->ForceSet(v8::Integer::New(1, isolate), formWrapper)) + if (!thisObject->ForceSet(v8::Integer::New(isolate(), 1), formWrapper)) return; - if (!thisObject->ForceSet(v8::Integer::New(2, isolate), documentWrapper)) + if (!thisObject->ForceSet(v8::Integer::New(isolate(), 2), documentWrapper)) return; // FIXME: Remove this code when we stop doing the 'with' hack above. - v8::Local<v8::Value> innerValue = V8ScriptRunner::callInternalFunction(intermediateFunction, thisObject, 0, 0, isolate); + v8::Local<v8::Value> innerValue = V8ScriptRunner::callInternalFunction(intermediateFunction, thisObject, 0, 0, isolate()); if (innerValue.IsEmpty() || !innerValue->IsFunction()) return; @@ -202,20 +209,12 @@ void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) // source returned (sometimes a RegExp is applied as well) for some // other use. That fails miserably if the actual wrapper source is // returned. - v8::Handle<v8::FunctionTemplate> toStringTemplate = - V8PerIsolateData::current()->lazyEventListenerToStringTemplate(); - if (toStringTemplate.IsEmpty()) - toStringTemplate = v8::FunctionTemplate::New(isolate, V8LazyEventListenerToString); - v8::Local<v8::Function> toStringFunction; - if (!toStringTemplate.IsEmpty()) - toStringFunction = toStringTemplate->GetFunction(); - if (!toStringFunction.IsEmpty()) { - String toStringString = "function " + m_functionName + "(" + m_eventParameterName + ") {\n " + m_code + "\n}"; - wrappedFunction->SetHiddenValue(V8HiddenPropertyName::toStringString(isolate), v8String(isolate, toStringString)); - wrappedFunction->Set(v8AtomicString(isolate, "toString"), toStringFunction); - } - - wrappedFunction->SetName(v8String(isolate, m_functionName)); + v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate(), V8LazyEventListenerToString); + ASSERT(!toStringFunction.IsEmpty()); + String toStringString = "function " + m_functionName + "(" + m_eventParameterName + ") {\n " + m_code + "\n}"; + V8HiddenValue::setHiddenValue(isolate(), wrappedFunction, V8HiddenValue::toStringString(isolate()), v8String(isolate(), toStringString)); + wrappedFunction->Set(v8AtomicString(isolate(), "toString"), toStringFunction); + wrappedFunction->SetName(v8String(isolate(), m_functionName)); // FIXME: Remove the following comment-outs. // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details. diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.h b/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.h index 4bc040ff95b..7ab4d7d7c18 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.h @@ -40,34 +40,38 @@ namespace WebCore { class Event; - class Frame; + class LocalFrame; class HTMLFormElement; class Node; // V8LazyEventListener is a wrapper for a JavaScript code string that is compiled and evaluated when an event is fired. // A V8LazyEventListener is either a HTML or SVG event handler. - class V8LazyEventListener : public V8AbstractEventListener { + class V8LazyEventListener FINAL : public V8AbstractEventListener { public: static PassRefPtr<V8LazyEventListener> create(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String& sourceURL, const TextPosition& position, Node* node, v8::Isolate* isolate) { return adoptRef(new V8LazyEventListener(functionName, eventParameterName, code, sourceURL, position, node, isolate)); } - virtual bool isLazy() const { return true; } + virtual bool isLazy() const OVERRIDE { return true; } + // V8LazyEventListener is always for the main world. + virtual DOMWrapperWorld& world() const OVERRIDE { return DOMWrapperWorld::mainWorld(); } + + virtual void handleEvent(ExecutionContext*, Event*) OVERRIDE; protected: - virtual void prepareListenerObject(ExecutionContext*); + virtual void prepareListenerObject(ExecutionContext*) OVERRIDE; private: V8LazyEventListener(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String sourceURL, const TextPosition&, Node*, v8::Isolate*); - virtual v8::Local<v8::Value> callListenerFunction(ExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); + virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*) OVERRIDE; // Needs to return true for all event handlers implemented in JavaScript so that // the SVG code does not add the event handler in both // SVGUseElement::buildShadowTree and again in // SVGUseElement::transferEventListenersToShadowTree - virtual bool wasCreatedFromMarkup() const { return true; } + virtual bool wasCreatedFromMarkup() const OVERRIDE { return true; } AtomicString m_functionName; AtomicString m_eventParameterName; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.cpp index 6be6f16d6fc..8e0581acdcc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.cpp @@ -26,44 +26,39 @@ #include "config.h" #include "bindings/v8/V8MutationCallback.h" -#include "V8MutationObserver.h" -#include "V8MutationRecord.h" +#include "bindings/core/v8/V8MutationObserver.h" +#include "bindings/core/v8/V8MutationRecord.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/ExecutionContext.h" #include "wtf/Assertions.h" namespace WebCore { -V8MutationCallback::V8MutationCallback(v8::Handle<v8::Function> callback, ExecutionContext* context, v8::Handle<v8::Object> owner, v8::Isolate* isolate) - : ActiveDOMCallback(context) - , m_callback(isolate, callback) - , m_world(DOMWrapperWorld::current()) - , m_isolate(isolate) +V8MutationCallback::V8MutationCallback(v8::Handle<v8::Function> callback, v8::Handle<v8::Object> owner, ScriptState* scriptState) + : ActiveDOMCallback(scriptState->executionContext()) + , m_callback(scriptState->isolate(), callback) + , m_scriptState(scriptState) { - owner->SetHiddenValue(V8HiddenPropertyName::callback(m_isolate), callback); + V8HiddenValue::setHiddenValue(scriptState->isolate(), owner, V8HiddenValue::callback(scriptState->isolate()), callback); m_callback.setWeak(this, &setWeakCallback); } -void V8MutationCallback::call(const Vector<RefPtr<MutationRecord> >& mutations, MutationObserver* observer) +void V8MutationCallback::call(const WillBeHeapVector<RefPtrWillBeMember<MutationRecord> >& mutations, MutationObserver* observer) { if (!canInvokeCallback()) return; - v8::HandleScope handleScope(m_isolate); + v8::Isolate* isolate = m_scriptState->isolate(); - v8::Handle<v8::Context> v8Context = toV8Context(executionContext(), m_world.get()); - if (v8Context.IsEmpty()) + if (m_scriptState->contextIsEmpty()) return; + ScriptState::Scope scope(m_scriptState.get()); - v8::Context::Scope scope(v8Context); - - v8::Handle<v8::Function> callback = m_callback.newLocal(m_isolate); - if (callback.IsEmpty()) + if (m_callback.isEmpty()) return; - - v8::Handle<v8::Value> observerHandle = toV8(observer, v8::Handle<v8::Object>(), m_isolate); + v8::Handle<v8::Value> observerHandle = toV8(observer, m_scriptState->context()->Global(), isolate); if (observerHandle.IsEmpty()) { if (!isScriptControllerTerminating()) CRASH(); @@ -74,11 +69,11 @@ void V8MutationCallback::call(const Vector<RefPtr<MutationRecord> >& mutations, return; v8::Handle<v8::Object> thisObject = v8::Handle<v8::Object>::Cast(observerHandle); - v8::Handle<v8::Value> argv[] = { v8Array(mutations, m_isolate), observerHandle }; + v8::Handle<v8::Value> argv[] = { v8Array(mutations, m_scriptState->context()->Global(), isolate), observerHandle }; v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); - ScriptController::callFunction(executionContext(), callback, thisObject, 2, argv, m_isolate); + ScriptController::callFunction(executionContext(), m_callback.newLocal(isolate), thisObject, WTF_ARRAY_LENGTH(argv), argv, isolate); } void V8MutationCallback::setWeakCallback(const v8::WeakCallbackData<v8::Function, V8MutationCallback>& data) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.h b/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.h index 93a4820998a..fc5589a629b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.h @@ -27,9 +27,8 @@ #define V8MutationCallback_h #include "bindings/v8/ActiveDOMCallback.h" -#include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/V8Utilities.h" +#include "bindings/v8/ScriptState.h" #include "core/dom/MutationCallback.h" #include "wtf/OwnPtr.h" #include "wtf/RefPtr.h" @@ -39,25 +38,23 @@ namespace WebCore { class ExecutionContext; -class V8MutationCallback : public MutationCallback, public ActiveDOMCallback { +class V8MutationCallback FINAL : public MutationCallback, public ActiveDOMCallback { public: - static PassOwnPtr<V8MutationCallback> create(v8::Handle<v8::Function> callback, ExecutionContext* context, v8::Handle<v8::Object> owner, v8::Isolate* isolate) + static PassOwnPtr<V8MutationCallback> create(v8::Handle<v8::Function> callback, v8::Handle<v8::Object> owner, ScriptState* scriptState) { - ASSERT(context); - return adoptPtr(new V8MutationCallback(callback, context, owner, isolate)); + return adoptPtr(new V8MutationCallback(callback, owner, scriptState)); } - virtual void call(const Vector<RefPtr<MutationRecord> >&, MutationObserver*) OVERRIDE; + virtual void call(const WillBeHeapVector<RefPtrWillBeMember<MutationRecord> >&, MutationObserver*) OVERRIDE; virtual ExecutionContext* executionContext() const OVERRIDE { return ContextLifecycleObserver::executionContext(); } private: - V8MutationCallback(v8::Handle<v8::Function>, ExecutionContext*, v8::Handle<v8::Object>, v8::Isolate*); + V8MutationCallback(v8::Handle<v8::Function>, v8::Handle<v8::Object>, ScriptState*); static void setWeakCallback(const v8::WeakCallbackData<v8::Function, V8MutationCallback>&); ScopedPersistent<v8::Function> m_callback; - RefPtr<DOMWrapperWorld> m_world; - v8::Isolate* m_isolate; + RefPtr<ScriptState> m_scriptState; }; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.cpp index 2912723fb82..a16369915c4 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.cpp @@ -32,17 +32,18 @@ #include "bindings/v8/V8NPObject.h" -#include "V8HTMLAppletElement.h" -#include "V8HTMLEmbedElement.h" -#include "V8HTMLObjectElement.h" +#include "bindings/core/v8/V8HTMLAppletElement.h" +#include "bindings/core/v8/V8HTMLEmbedElement.h" +#include "bindings/core/v8/V8HTMLObjectElement.h" #include "bindings/v8/NPV8Object.h" -#include "bindings/v8/UnsafePersistent.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8NPUtils.h" #include "bindings/v8/V8ObjectConstructor.h" +#include "bindings/v8/V8PersistentValueMap.h" #include "bindings/v8/npruntime_impl.h" #include "bindings/v8/npruntime_priv.h" #include "core/html/HTMLPlugInElement.h" +#include "v8-util.h" #include "wtf/OwnPtr.h" namespace WebCore { @@ -69,21 +70,18 @@ struct IdentifierRep { static void npObjectInvokeImpl(const v8::FunctionCallbackInfo<v8::Value>& info, InvokeFunctionType functionId) { NPObject* npObject; + v8::Isolate* isolate = info.GetIsolate(); - WrapperWorldType currentWorldType = worldType(info.GetIsolate()); // These three types are subtypes of HTMLPlugInElement. - if (V8HTMLAppletElement::hasInstance(info.Holder(), info.GetIsolate(), currentWorldType) || V8HTMLEmbedElement::hasInstance(info.Holder(), info.GetIsolate(), currentWorldType) - || V8HTMLObjectElement::hasInstance(info.Holder(), info.GetIsolate(), currentWorldType)) { - // The holder object is a subtype of HTMLPlugInElement. - HTMLPlugInElement* element; - if (V8HTMLAppletElement::hasInstance(info.Holder(), info.GetIsolate(), currentWorldType)) - element = V8HTMLAppletElement::toNative(info.Holder()); - else if (V8HTMLEmbedElement::hasInstance(info.Holder(), info.GetIsolate(), currentWorldType)) - element = V8HTMLEmbedElement::toNative(info.Holder()); - else - element = V8HTMLObjectElement::toNative(info.Holder()); + HTMLPlugInElement* element = V8HTMLAppletElement::toNativeWithTypeCheck(isolate, info.Holder()); + if (!element) { + element = V8HTMLEmbedElement::toNativeWithTypeCheck(isolate, info.Holder()); + if (!element) { + element = V8HTMLObjectElement::toNativeWithTypeCheck(isolate, info.Holder()); + } + } + if (element) { if (RefPtr<SharedPersistent<v8::Object> > wrapper = element->pluginWrapper()) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); npObject = v8ObjectToNPObject(wrapper->newLocal(isolate)); } else @@ -101,7 +99,7 @@ static void npObjectInvokeImpl(const v8::FunctionCallbackInfo<v8::Value>& info, // Verify that our wrapper wasn't using a NPObject which has already been deleted. if (!npObject || !_NPN_IsAlive(npObject)) { - throwError(v8ReferenceError, "NPObject deleted", info.GetIsolate()); + throwError(v8ReferenceError, "NPObject deleted", isolate); return; } @@ -110,7 +108,7 @@ static void npObjectInvokeImpl(const v8::FunctionCallbackInfo<v8::Value>& info, OwnPtr<NPVariant[]> npArgs = adoptArrayPtr(new NPVariant[numArgs]); for (int i = 0; i < numArgs; i++) - convertV8ObjectToNPVariant(info[i], npObject, &npArgs[i], info.GetIsolate()); + convertV8ObjectToNPVariant(info[i], npObject, &npArgs[i], isolate); NPVariant result; VOID_TO_NPVARIANT(result); @@ -137,7 +135,7 @@ static void npObjectInvokeImpl(const v8::FunctionCallbackInfo<v8::Value>& info, } if (!retval) - throwError(v8GeneralError, "Error calling method on NPObject.", info.GetIsolate()); + throwError(v8GeneralError, "Error calling method on NPObject.", isolate); for (int i = 0; i < numArgs; i++) _NPN_ReleaseVariantValue(&npArgs[i]); @@ -145,7 +143,7 @@ static void npObjectInvokeImpl(const v8::FunctionCallbackInfo<v8::Value>& info, // Unwrap return values. v8::Handle<v8::Value> returnValue; if (_NPN_IsAlive(npObject)) - returnValue = convertNPVariantToV8Object(&result, npObject, info.GetIsolate()); + returnValue = convertNPVariantToV8Object(&result, npObject, isolate); _NPN_ReleaseVariantValue(&result); v8SetReturnValue(info, returnValue); @@ -168,54 +166,72 @@ void npObjectInvokeDefaultHandler(const v8::FunctionCallbackInfo<v8::Value>& inf npObjectInvokeImpl(info, InvokeDefault); } +class V8TemplateMapTraits : public V8PersistentValueMapTraits<PrivateIdentifier*, v8::FunctionTemplate, true> { +public: + typedef v8::PersistentValueMap<PrivateIdentifier*, v8::FunctionTemplate, V8TemplateMapTraits> MapType; + typedef PrivateIdentifier WeakCallbackDataType; + + static WeakCallbackDataType* WeakCallbackParameter(MapType* map, PrivateIdentifier* key, const v8::Local<v8::FunctionTemplate>& value) + { + return key; + } + + static void DisposeCallbackData(WeakCallbackDataType* callbackData) { } + + static MapType* MapFromWeakCallbackData( + const v8::WeakCallbackData<v8::FunctionTemplate, WeakCallbackDataType>&); + + static PrivateIdentifier* KeyFromWeakCallbackData( + const v8::WeakCallbackData<v8::FunctionTemplate, WeakCallbackDataType>& data) + { + return data.GetParameter(); + } + + // Dispose traits: + static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<v8::FunctionTemplate> value, PrivateIdentifier* key) { } +}; + + class V8NPTemplateMap { public: // NPIdentifier is PrivateIdentifier*. - typedef HashMap<PrivateIdentifier*, UnsafePersistent<v8::FunctionTemplate> > MapType; + typedef v8::PersistentValueMap<PrivateIdentifier*, v8::FunctionTemplate, V8TemplateMapTraits> MapType; - UnsafePersistent<v8::FunctionTemplate> get(PrivateIdentifier* key) + v8::Local<v8::FunctionTemplate> get(PrivateIdentifier* key) { - return m_map.get(key); + return m_map.Get(key); } void set(PrivateIdentifier* key, v8::Handle<v8::FunctionTemplate> handle) { - ASSERT(!m_map.contains(key)); - v8::Persistent<v8::FunctionTemplate> wrapper(m_isolate, handle); - wrapper.SetWeak(key, &setWeakCallback); - m_map.set(key, UnsafePersistent<v8::FunctionTemplate>(wrapper)); + ASSERT(!m_map.Contains(key)); + m_map.Set(key, handle); } static V8NPTemplateMap& sharedInstance(v8::Isolate* isolate) { DEFINE_STATIC_LOCAL(V8NPTemplateMap, map, (isolate)); - ASSERT(isolate == map.m_isolate); + ASSERT(isolate == map.m_map.GetIsolate()); return map; } + friend class V8TemplateMapTraits; + private: explicit V8NPTemplateMap(v8::Isolate* isolate) - : m_isolate(isolate) - { - } - - void clear(PrivateIdentifier* key) + : m_map(isolate) { - MapType::iterator it = m_map.find(key); - ASSERT_WITH_SECURITY_IMPLICATION(it != m_map.end()); - it->value.dispose(); - m_map.remove(it); - } - - static void setWeakCallback(const v8::WeakCallbackData<v8::FunctionTemplate, PrivateIdentifier>& data) - { - V8NPTemplateMap::sharedInstance(data.GetIsolate()).clear(data.GetParameter()); } MapType m_map; - v8::Isolate* m_isolate; }; +V8TemplateMapTraits::MapType* V8TemplateMapTraits::MapFromWeakCallbackData(const v8::WeakCallbackData<v8::FunctionTemplate, WeakCallbackDataType>& data) +{ + return &V8NPTemplateMap::sharedInstance(data.GetIsolate()).m_map; +} + + static v8::Handle<v8::Value> npObjectGetProperty(v8::Local<v8::Object> self, NPIdentifier identifier, v8::Local<v8::Value> key, v8::Isolate* isolate) { NPObject* npObject = v8ObjectToNPObject(self); @@ -251,19 +267,15 @@ static v8::Handle<v8::Value> npObjectGetProperty(v8::Local<v8::Object> self, NPI return throwError(v8ReferenceError, "NPObject deleted", isolate); PrivateIdentifier* id = static_cast<PrivateIdentifier*>(identifier); - UnsafePersistent<v8::FunctionTemplate> functionTemplate = V8NPTemplateMap::sharedInstance(isolate).get(id); - // FunctionTemplate caches function for each context. - v8::Local<v8::Function> v8Function; + v8::Local<v8::FunctionTemplate> functionTemplate = V8NPTemplateMap::sharedInstance(isolate).get(id); // Cache templates using identifier as the key. - if (functionTemplate.isEmpty()) { + if (functionTemplate.IsEmpty()) { // Create a new template. - v8::Local<v8::FunctionTemplate> temp = v8::FunctionTemplate::New(isolate); - temp->SetCallHandler(npObjectMethodHandler, key); - V8NPTemplateMap::sharedInstance(isolate).set(id, temp); - v8Function = temp->GetFunction(); - } else { - v8Function = functionTemplate.newLocal(isolate)->GetFunction(); + functionTemplate = v8::FunctionTemplate::New(isolate); + functionTemplate->SetCallHandler(npObjectMethodHandler, key); + V8NPTemplateMap::sharedInstance(isolate).set(id, functionTemplate); } + v8::Local<v8::Function> v8Function = functionTemplate->GetFunction(); v8Function->SetName(v8::Handle<v8::String>::Cast(key)); return v8Function; } @@ -367,13 +379,22 @@ void npObjectPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info, uint32_t count; NPIdentifier* identifiers; if (npObject->_class->enumerate(npObject, &identifiers, &count)) { - v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), count); + uint32_t propertiesCount = 0; for (uint32_t i = 0; i < count; ++i) { IdentifierRep* identifier = static_cast<IdentifierRep*>(identifiers[i]); - if (namedProperty) - properties->Set(v8::Integer::New(i, info.GetIsolate()), v8AtomicString(info.GetIsolate(), identifier->string())); - else - properties->Set(v8::Integer::New(i, info.GetIsolate()), v8::Integer::New(identifier->number(), info.GetIsolate())); + if (namedProperty == identifier->m_isString) + ++propertiesCount; + } + v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), propertiesCount); + for (uint32_t i = 0, propertyIndex = 0; i < count; ++i) { + IdentifierRep* identifier = static_cast<IdentifierRep*>(identifiers[i]); + if (namedProperty == identifier->m_isString) { + ASSERT(propertyIndex < propertiesCount); + if (namedProperty) + properties->Set(v8::Integer::New(info.GetIsolate(), propertyIndex++), v8AtomicString(info.GetIsolate(), identifier->string())); + else + properties->Set(v8::Integer::New(info.GetIsolate(), propertyIndex++), v8::Integer::New(info.GetIsolate(), identifier->number())); + } } v8SetReturnValue(info, properties); @@ -398,18 +419,13 @@ static DOMWrapperMap<NPObject>& staticNPObjectMap() return npObjectMap; } -template<> -inline void DOMWrapperMap<NPObject>::setWeakCallback(const v8::WeakCallbackData<v8::Object, DOMWrapperMap<NPObject> >& data) +template <> +inline void DOMWrapperMap<NPObject>::PersistentValueMapTraits::Dispose( + v8::Isolate* isolate, + v8::UniquePersistent<v8::Object> value, + NPObject* npObject) { - NPObject* npObject = static_cast<NPObject*>(toNative(data.GetValue())); - ASSERT(npObject); - ASSERT(staticNPObjectMap().containsKeyAndValue(npObject, data.GetValue())); - - // Must remove from our map before calling _NPN_ReleaseObject(). _NPN_ReleaseObject can - // call forgetV8ObjectForNPObject, which uses the table as well. - staticNPObjectMap().removeAndDispose(npObject); - if (_NPN_IsAlive(npObject)) _NPN_ReleaseObject(npObject); } @@ -447,7 +463,7 @@ v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root // V8DOMWrapper::associateObjectWithWrapper() // to create a wrapper object. v8::Handle<v8::Function> v8Function = npObjectDesc.Get(isolate)->GetFunction(); - v8::Local<v8::Object> value = V8ObjectConstructor::newInstance(v8Function); + v8::Local<v8::Object> value = V8ObjectConstructor::newInstance(isolate, v8Function); if (value.IsEmpty()) return value; @@ -459,7 +475,7 @@ v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root WrapperConfiguration configuration = buildWrapperConfiguration(object, WrapperConfiguration::Dependent); staticNPObjectMap().set(object, value, configuration); - ASSERT(V8DOMWrapper::maybeDOMWrapper(value)); + ASSERT(V8DOMWrapper::isDOMWrapper(value)); return value; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.h b/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.h index 4465b039868..dc5d336fbe5 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.h @@ -31,9 +31,10 @@ #ifndef V8NPObject_h #define V8NPObject_h -#include <bindings/npruntime.h> #include <v8.h> +struct NPObject; + namespace WebCore { // These functions can be replaced by normal JS operation. diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8NPUtils.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8NPUtils.cpp index 7c0645f7a1f..df6eefe3b42 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8NPUtils.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8NPUtils.cpp @@ -36,7 +36,7 @@ #include "bindings/v8/V8NPObject.h" #include "bindings/v8/npruntime_impl.h" #include "bindings/v8/npruntime_priv.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "wtf/text/WTFString.h" #include <stdlib.h> @@ -69,7 +69,7 @@ void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NP str->WriteUtf8(utf8Chars, length, 0, v8::String::HINT_MANY_WRITES_EXPECTED); STRINGN_TO_NPVARIANT(utf8Chars, length-1, *result); } else if (object->IsObject()) { - DOMWindow* window = toDOMWindow(isolate->GetCurrentContext()); + LocalDOMWindow* window = currentDOMWindow(isolate); NPObject* npobject = npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(object), window, isolate); if (npobject) _NPN_RegisterObject(npobject, owner); @@ -83,7 +83,7 @@ v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant* variant, NPObj switch (type) { case NPVariantType_Int32: - return v8::Integer::New(NPVARIANT_TO_INT32(*variant), isolate); + return v8::Integer::New(isolate, NPVARIANT_TO_INT32(*variant)); case NPVariantType_Double: return v8::Number::New(isolate, NPVARIANT_TO_DOUBLE(*variant)); case NPVariantType_Bool: diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.cpp index 3fcbc3c0f94..deecfa7b5c6 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.cpp @@ -31,35 +31,41 @@ #include "config.h" #include "bindings/v8/V8NodeFilterCondition.h" -#include "V8Node.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/ScriptController.h" -#include "bindings/v8/ScriptState.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/Node.h" #include "core/dom/NodeFilter.h" #include "wtf/OwnPtr.h" namespace WebCore { -V8NodeFilterCondition::V8NodeFilterCondition(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, v8::Isolate* isolate) - : m_filter(isolate, filter) +V8NodeFilterCondition::V8NodeFilterCondition(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, ScriptState* scriptState) + : m_scriptState(scriptState) { - owner->SetHiddenValue(V8HiddenPropertyName::condition(isolate), filter); - m_filter.setWeak(this, &setWeakCallback); + // ..acceptNode(..) will only dispatch m_filter if m_filter->IsObject(). + // We'll make sure m_filter is either usable by acceptNode or empty. + // (See the fast/dom/node-filter-gc test for a case where 'empty' happens.) + if (!filter.IsEmpty() && filter->IsObject()) { + V8HiddenValue::setHiddenValue(scriptState->isolate(), owner, V8HiddenValue::condition(scriptState->isolate()), filter); + m_filter.set(scriptState->isolate(), filter); + m_filter.setWeak(this, &setWeakCallback); + } } V8NodeFilterCondition::~V8NodeFilterCondition() { } -short V8NodeFilterCondition::acceptNode(ScriptState* state, Node* node) const +short V8NodeFilterCondition::acceptNode(Node* node, ExceptionState& exceptionState) const { - v8::Isolate* isolate = state->isolate(); - ASSERT(isolate->InContext()); + v8::Isolate* isolate = m_scriptState->isolate(); + ASSERT(!m_scriptState->context().IsEmpty()); v8::HandleScope handleScope(isolate); v8::Handle<v8::Value> filter = m_filter.newLocal(isolate); - ASSERT(!filter.IsEmpty()); - if (!filter->IsObject()) + + ASSERT(filter.IsEmpty() || filter->IsObject()); + if (filter.IsEmpty()) return NodeFilter::FILTER_ACCEPT; v8::TryCatch exceptionCatcher; @@ -69,21 +75,21 @@ short V8NodeFilterCondition::acceptNode(ScriptState* state, Node* node) const callback = v8::Handle<v8::Function>::Cast(filter); else { v8::Local<v8::Value> value = filter->ToObject()->Get(v8AtomicString(isolate, "acceptNode")); - if (!value->IsFunction()) { - throwTypeError("NodeFilter object does not have an acceptNode function", state->isolate()); + if (value.IsEmpty() || !value->IsFunction()) { + exceptionState.throwTypeError("NodeFilter object does not have an acceptNode function"); return NodeFilter::FILTER_REJECT; } callback = v8::Handle<v8::Function>::Cast(value); } OwnPtr<v8::Handle<v8::Value>[]> info = adoptArrayPtr(new v8::Handle<v8::Value>[1]); - info[0] = toV8(node, v8::Handle<v8::Object>(), state->isolate()); + v8::Handle<v8::Object> context = m_scriptState->context()->Global(); + info[0] = toV8(node, context, isolate); - v8::Handle<v8::Object> object = isolate->GetCurrentContext()->Global(); - v8::Handle<v8::Value> result = ScriptController::callFunction(state->executionContext(), callback, object, 1, info.get(), isolate); + v8::Handle<v8::Value> result = ScriptController::callFunction(m_scriptState->executionContext(), callback, context, 1, info.get(), isolate); if (exceptionCatcher.HasCaught()) { - state->setException(exceptionCatcher.Exception()); + exceptionState.rethrowV8Exception(exceptionCatcher.Exception()); return NodeFilter::FILTER_REJECT; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.h b/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.h index 3d87020d5f2..de42cb5c13a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.h @@ -32,14 +32,16 @@ #define V8NodeFilterCondition_h #include "bindings/v8/ScopedPersistent.h" +#include "bindings/v8/ScriptState.h" #include "core/dom/NodeFilterCondition.h" +#include "platform/heap/Handle.h" #include <v8.h> #include "wtf/PassRefPtr.h" namespace WebCore { class Node; -class ScriptState; +class ExceptionState; // V8NodeFilterCondition maintains a Javascript implemented callback for // filtering Node returned by NodeIterator/TreeWalker. @@ -58,25 +60,26 @@ class ScriptState; // v | v | v // NodeIterator --HiddenValue--> NodeFilter --HiddenValue--> JS Callback // (V8) -class V8NodeFilterCondition : public NodeFilterCondition { +class V8NodeFilterCondition FINAL : public NodeFilterCondition { public: - static PassRefPtr<V8NodeFilterCondition> create(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, v8::Isolate* isolate) + static PassRefPtrWillBeRawPtr<V8NodeFilterCondition> create(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, ScriptState* scriptState) { - return adoptRef(new V8NodeFilterCondition(filter, owner, isolate)); + return adoptRefWillBeNoop(new V8NodeFilterCondition(filter, owner, scriptState)); } virtual ~V8NodeFilterCondition(); - virtual short acceptNode(ScriptState*, Node*) const; + virtual short acceptNode(Node*, ExceptionState&) const OVERRIDE; private: // As the value |filter| is maintained by V8GC, the |owner| which references // V8NodeFilterCondition, usually a wrapper of NodeFilter, is specified here // to hold a strong reference to |filter|. - V8NodeFilterCondition(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, v8::Isolate*); + V8NodeFilterCondition(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, ScriptState*); static void setWeakCallback(const v8::WeakCallbackData<v8::Value, V8NodeFilterCondition>&); + RefPtr<ScriptState> m_scriptState; ScopedPersistent<v8::Value> m_filter; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.cpp index 6ebfbab7b71..d52bdc1a910 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.cpp @@ -28,46 +28,38 @@ #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ScriptRunner.h" #include "core/dom/Document.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "platform/TraceEvent.h" namespace WebCore { -v8::Local<v8::Object> V8ObjectConstructor::newInstance(v8::Handle<v8::Function> function) +v8::Local<v8::Object> V8ObjectConstructor::newInstance(v8::Isolate* isolate, v8::Handle<v8::Function> function) { if (function.IsEmpty()) return v8::Local<v8::Object>(); - ConstructorMode constructorMode; - return V8ScriptRunner::instantiateObject(function); + ConstructorMode constructorMode(isolate); + return V8ScriptRunner::instantiateObject(isolate, function); } -v8::Local<v8::Object> V8ObjectConstructor::newInstance(v8::Handle<v8::ObjectTemplate> objectTemplate) -{ - if (objectTemplate.IsEmpty()) - return v8::Local<v8::Object>(); - ConstructorMode constructorMode; - return V8ScriptRunner::instantiateObject(objectTemplate); -} - -v8::Local<v8::Object> V8ObjectConstructor::newInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) +v8::Local<v8::Object> V8ObjectConstructor::newInstance(v8::Isolate* isolate, v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) { if (function.IsEmpty()) return v8::Local<v8::Object>(); - ConstructorMode constructorMode; - return V8ScriptRunner::instantiateObject(function, argc, argv); + ConstructorMode constructorMode(isolate); + return V8ScriptRunner::instantiateObject(isolate, function, argc, argv); } -v8::Local<v8::Object> V8ObjectConstructor::newInstanceInDocument(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[], Document* document) +v8::Local<v8::Object> V8ObjectConstructor::newInstanceInDocument(v8::Isolate* isolate, v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[], Document* document) { if (function.IsEmpty()) return v8::Local<v8::Object>(); - return V8ScriptRunner::instantiateObjectInDocument(function, document, argc, argv); + return V8ScriptRunner::instantiateObjectInDocument(isolate, function, document, argc, argv); } void V8ObjectConstructor::isValidConstructorMode(const v8::FunctionCallbackInfo<v8::Value>& info) { - if (ConstructorMode::current() == ConstructorMode::CreateNewObject) { + if (ConstructorMode::current(info.GetIsolate()) == ConstructorMode::CreateNewObject) { throwTypeError("Illegal constructor", info.GetIsolate()); return; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.h b/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.h index 2c9f6a26020..e1d204fa606 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.h @@ -32,6 +32,7 @@ #define V8ObjectConstructor_h #include "bindings/v8/V8PerIsolateData.h" +#include "bindings/v8/V8RecursionScope.h" #include <v8.h> @@ -46,31 +47,37 @@ public: CreateNewObject }; - ConstructorMode() + ConstructorMode(v8::Isolate* isolate) + : m_isolate(isolate) + , m_microtaskSuppression(isolate) { - V8PerIsolateData* data = V8PerIsolateData::current(); + V8PerIsolateData* data = V8PerIsolateData::from(m_isolate); m_previous = data->m_constructorMode; data->m_constructorMode = WrapExistingObject; } ~ConstructorMode() { - V8PerIsolateData* data = V8PerIsolateData::current(); + V8PerIsolateData* data = V8PerIsolateData::from(m_isolate); data->m_constructorMode = m_previous; } - static bool current() { return V8PerIsolateData::current()->m_constructorMode; } + static bool current(v8::Isolate* isolate) + { + return V8PerIsolateData::from(isolate)->m_constructorMode; + } private: + v8::Isolate* m_isolate; bool m_previous; + V8RecursionScope::MicrotaskSuppression m_microtaskSuppression; }; class V8ObjectConstructor { public: - static v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>); - static v8::Local<v8::Object> newInstance(v8::Handle<v8::ObjectTemplate>); - static v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>, int, v8::Handle<v8::Value> argv[]); - static v8::Local<v8::Object> newInstanceInDocument(v8::Handle<v8::Function>, int, v8::Handle<v8::Value> argv[], Document*); + static v8::Local<v8::Object> newInstance(v8::Isolate*, v8::Handle<v8::Function>); + static v8::Local<v8::Object> newInstance(v8::Isolate*, v8::Handle<v8::Function>, int, v8::Handle<v8::Value> argv[]); + static v8::Local<v8::Object> newInstanceInDocument(v8::Isolate*, v8::Handle<v8::Function>, int, v8::Handle<v8::Value> argv[], Document*); static void isValidConstructorMode(const v8::FunctionCallbackInfo<v8::Value>&); }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.cpp index 8bf80076f08..1456bed0748 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "bindings/v8/V8PerContextData.h" +#include "bindings/v8/ScriptState.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ObjectConstructor.h" #include "wtf/StringExtras.h" @@ -39,67 +40,49 @@ namespace WebCore { -template<typename Map> -static void disposeMapWithUnsafePersistentValues(Map* map) +V8PerContextData::V8PerContextData(v8::Handle<v8::Context> context) + : m_wrapperBoilerplates(context->GetIsolate()) + , m_constructorMap(context->GetIsolate()) + , m_isolate(context->GetIsolate()) + , m_contextHolder(adoptPtr(new gin::ContextHolder(context->GetIsolate()))) + , m_context(m_isolate, context) + , m_customElementBindings(adoptPtr(new CustomElementBindingMap())) + , m_activityLogger(0) { - typename Map::iterator it = map->begin(); - for (; it != map->end(); ++it) - it->value.dispose(); - map->clear(); + m_contextHolder->SetContext(context); + + v8::Context::Scope contextScope(context); + ASSERT(m_errorPrototype.isEmpty()); + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(v8AtomicString(m_isolate, "Error"))); + ASSERT(!object.IsEmpty()); + v8::Handle<v8::Value> prototypeValue = object->Get(v8AtomicString(m_isolate, "prototype")); + ASSERT(!prototypeValue.IsEmpty()); + m_errorPrototype.set(m_isolate, prototypeValue); } -void V8PerContextData::dispose() +V8PerContextData::~V8PerContextData() { - v8::HandleScope handleScope(m_isolate); - V8PerContextDataHolder::from(v8::Local<v8::Context>::New(m_isolate, m_context))->setPerContextData(0); - - disposeMapWithUnsafePersistentValues(&m_wrapperBoilerplates); - disposeMapWithUnsafePersistentValues(&m_constructorMap); - m_customElementBindings.clear(); - - m_context.Reset(); } -#define V8_STORE_PRIMORDIAL(name, Name) \ -{ \ - ASSERT(m_##name##Prototype.isEmpty()); \ - v8::Handle<v8::String> symbol = v8::String::NewFromUtf8(m_isolate, #Name, v8::String::kInternalizedString); \ - if (symbol.IsEmpty()) \ - return false; \ - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(v8::Local<v8::Context>::New(m_isolate, m_context)->Global()->Get(symbol)); \ - if (object.IsEmpty()) \ - return false; \ - v8::Handle<v8::Value> prototypeValue = object->Get(prototypeString); \ - if (prototypeValue.IsEmpty()) \ - return false; \ - m_##name##Prototype.set(m_isolate, prototypeValue); \ +PassOwnPtr<V8PerContextData> V8PerContextData::create(v8::Handle<v8::Context> context) +{ + return adoptPtr(new V8PerContextData(context)); } -bool V8PerContextData::init() +V8PerContextData* V8PerContextData::from(v8::Handle<v8::Context> context) { - v8::Handle<v8::Context> context = v8::Local<v8::Context>::New(m_isolate, m_context); - V8PerContextDataHolder::from(context)->setPerContextData(this); - - v8::Handle<v8::String> prototypeString = v8AtomicString(m_isolate, "prototype"); - if (prototypeString.IsEmpty()) - return false; - - V8_STORE_PRIMORDIAL(error, Error); - - return true; + return ScriptState::from(context)->perContextData(); } -#undef V8_STORE_PRIMORDIAL - v8::Local<v8::Object> V8PerContextData::createWrapperFromCacheSlowCase(const WrapperTypeInfo* type) { ASSERT(!m_errorPrototype.isEmpty()); - v8::Context::Scope scope(v8::Local<v8::Context>::New(m_isolate, m_context)); + v8::Context::Scope scope(context()); v8::Local<v8::Function> function = constructorForType(type); - v8::Local<v8::Object> instanceTemplate = V8ObjectConstructor::newInstance(function); + v8::Local<v8::Object> instanceTemplate = V8ObjectConstructor::newInstance(m_isolate, function); if (!instanceTemplate.IsEmpty()) { - m_wrapperBoilerplates.set(type, UnsafePersistent<v8::Object>(m_isolate, instanceTemplate)); + m_wrapperBoilerplates.Set(type, instanceTemplate); return instanceTemplate->Clone(); } return v8::Local<v8::Object>(); @@ -109,8 +92,8 @@ v8::Local<v8::Function> V8PerContextData::constructorForTypeSlowCase(const Wrapp { ASSERT(!m_errorPrototype.isEmpty()); - v8::Context::Scope scope(v8::Local<v8::Context>::New(m_isolate, m_context)); - v8::Handle<v8::FunctionTemplate> functionTemplate = type->domTemplate(m_isolate, worldType(m_isolate)); + v8::Context::Scope scope(context()); + v8::Handle<v8::FunctionTemplate> functionTemplate = type->domTemplate(m_isolate); // Getting the function might fail if we're running out of stack or memory. v8::TryCatch tryCatch; v8::Local<v8::Function> function = functionTemplate->GetFunction(); @@ -131,11 +114,11 @@ v8::Local<v8::Function> V8PerContextData::constructorForTypeSlowCase(const Wrapp && type->wrapperTypePrototype == WrapperTypeObjectPrototype) prototypeObject->SetAlignedPointerInInternalField(v8PrototypeTypeIndex, const_cast<WrapperTypeInfo*>(type)); type->installPerContextEnabledMethods(prototypeObject, m_isolate); - if (type->wrapperTypePrototype == WrapperTypeErrorPrototype) + if (type->wrapperTypePrototype == WrapperTypeExceptionPrototype) prototypeObject->SetPrototype(m_errorPrototype.newLocal(m_isolate)); } - m_constructorMap.set(type, UnsafePersistent<v8::Function>(m_isolate, function)); + m_constructorMap.Set(type, function); return function; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.h b/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.h index 63634f85cbe..7987c616892 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.h @@ -33,8 +33,7 @@ #include "bindings/v8/CustomElementBinding.h" #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/UnsafePersistent.h" -#include "bindings/v8/V8DOMActivityLogger.h" +#include "bindings/v8/V8PersistentValueMap.h" #include "bindings/v8/WrapperTypeInfo.h" #include "gin/public/context_holder.h" #include "gin/public/gin_embedders.h" @@ -48,7 +47,7 @@ namespace WebCore { class CustomElementDefinition; -class DOMWrapperWorld; +class V8DOMActivityLogger; class V8PerContextData; struct V8NPObject; typedef WTF::Vector<V8NPObject*> V8NPObjectVector; @@ -59,139 +58,69 @@ enum V8ContextEmbedderDataField { v8ContextPerContextDataIndex = static_cast<int>(gin::kPerContextDataStartIndex + gin::kEmbedderBlink), }; -class V8PerContextDataHolder { - WTF_MAKE_NONCOPYABLE(V8PerContextDataHolder); -public: - static void install(v8::Handle<v8::Context> context) - { - new V8PerContextDataHolder(context); - } - - static V8PerContextDataHolder* from(v8::Handle<v8::Context> context) - { - return static_cast<V8PerContextDataHolder*>(context->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex)); - } - - V8PerContextData* perContextData() const { return m_perContextData; } - void setPerContextData(V8PerContextData* data) { m_perContextData = data; } - - DOMWrapperWorld* isolatedWorld() const { return m_isolatedWorld; } - void setIsolatedWorld(DOMWrapperWorld* world) { m_isolatedWorld = world; } - -private: - explicit V8PerContextDataHolder(v8::Handle<v8::Context> context) - : m_context(v8::Isolate::GetCurrent(), context) - , m_perContextData(0) - , m_isolatedWorld(0) - { - m_context.SetWeak(this, &V8PerContextDataHolder::weakCallback); - context->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, this); - } - - ~V8PerContextDataHolder() {} - - static void weakCallback(const v8::WeakCallbackData<v8::Context, V8PerContextDataHolder>& data) - { - data.GetValue()->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, 0); - data.GetParameter()->m_context.Reset(); - delete data.GetParameter(); - } - - v8::Persistent<v8::Context> m_context; - V8PerContextData* m_perContextData; - DOMWrapperWorld* m_isolatedWorld; -}; - class V8PerContextData { public: - static PassOwnPtr<V8PerContextData> create(v8::Handle<v8::Context> context) - { - return adoptPtr(new V8PerContextData(context)); - } + static PassOwnPtr<V8PerContextData> create(v8::Handle<v8::Context>); - ~V8PerContextData() - { - dispose(); - } + static V8PerContextData* from(v8::Handle<v8::Context>); - bool init(); + ~V8PerContextData(); - static V8PerContextData* from(v8::Handle<v8::Context> context) - { - return V8PerContextDataHolder::from(context)->perContextData(); - } + v8::Handle<v8::Context> context() { return m_context.newLocal(m_isolate); } // To create JS Wrapper objects, we create a cache of a 'boiler plate' // object, and then simply Clone that object each time we need a new one. // This is faster than going through the full object creation process. v8::Local<v8::Object> createWrapperFromCache(const WrapperTypeInfo* type) { - UnsafePersistent<v8::Object> boilerplate = m_wrapperBoilerplates.get(type); - return !boilerplate.isEmpty() ? boilerplate.newLocal(v8::Isolate::GetCurrent())->Clone() : createWrapperFromCacheSlowCase(type); + v8::Local<v8::Object> boilerplate = m_wrapperBoilerplates.Get(type); + return !boilerplate.IsEmpty() ? boilerplate->Clone() : createWrapperFromCacheSlowCase(type); } v8::Local<v8::Function> constructorForType(const WrapperTypeInfo* type) { - UnsafePersistent<v8::Function> function = m_constructorMap.get(type); - if (!function.isEmpty()) - return function.newLocal(v8::Isolate::GetCurrent()); - return constructorForTypeSlowCase(type); + v8::Local<v8::Function> function = m_constructorMap.Get(type); + return (!function.IsEmpty()) ? function : constructorForTypeSlowCase(type); } v8::Local<v8::Object> prototypeForType(const WrapperTypeInfo*); - V8NPObjectMap* v8NPObjectMap() - { - return &m_v8NPObjectMap; - } - - V8DOMActivityLogger* activityLogger() - { - return m_activityLogger; - } - - void setActivityLogger(V8DOMActivityLogger* logger) - { - m_activityLogger = logger; - } + V8NPObjectMap* v8NPObjectMap() { return &m_v8NPObjectMap; } void addCustomElementBinding(CustomElementDefinition*, PassOwnPtr<CustomElementBinding>); void clearCustomElementBinding(CustomElementDefinition*); CustomElementBinding* customElementBinding(CustomElementDefinition*); -private: - explicit V8PerContextData(v8::Handle<v8::Context> context) - : m_activityLogger(0) - , m_isolate(v8::Isolate::GetCurrent()) - , m_context(m_isolate, context) - , m_customElementBindings(adoptPtr(new CustomElementBindingMap())) - { - } + V8DOMActivityLogger* activityLogger() const { return m_activityLogger; } + void setActivityLogger(V8DOMActivityLogger* activityLogger) { m_activityLogger = activityLogger; } - void dispose(); +private: + V8PerContextData(v8::Handle<v8::Context>); v8::Local<v8::Object> createWrapperFromCacheSlowCase(const WrapperTypeInfo*); v8::Local<v8::Function> constructorForTypeSlowCase(const WrapperTypeInfo*); // For each possible type of wrapper, we keep a boilerplate object. // The boilerplate is used to create additional wrappers of the same type. - typedef WTF::HashMap<const WrapperTypeInfo*, UnsafePersistent<v8::Object> > WrapperBoilerplateMap; + typedef V8PersistentValueMap<const WrapperTypeInfo*, v8::Object, false> WrapperBoilerplateMap; WrapperBoilerplateMap m_wrapperBoilerplates; - typedef WTF::HashMap<const WrapperTypeInfo*, UnsafePersistent<v8::Function> > ConstructorMap; + typedef V8PersistentValueMap<const WrapperTypeInfo*, v8::Function, false> ConstructorMap; ConstructorMap m_constructorMap; V8NPObjectMap m_v8NPObjectMap; - // We cache a pointer to the V8DOMActivityLogger associated with the world - // corresponding to this context. The ownership of the pointer is retained - // by the DOMActivityLoggerMap in DOMWrapperWorld. - V8DOMActivityLogger* m_activityLogger; + v8::Isolate* m_isolate; - v8::Persistent<v8::Context> m_context; + OwnPtr<gin::ContextHolder> m_contextHolder; + + ScopedPersistent<v8::Context> m_context; ScopedPersistent<v8::Value> m_errorPrototype; typedef WTF::HashMap<CustomElementDefinition*, OwnPtr<CustomElementBinding> > CustomElementBindingMap; OwnPtr<CustomElementBindingMap> m_customElementBindings; + + // This is owned by a static hash map in V8DOMActivityLogger. + V8DOMActivityLogger* m_activityLogger; }; class V8PerContextDebugData { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.cpp index 10064bc2dde..43dd26351e8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.cpp @@ -27,48 +27,74 @@ #include "bindings/v8/V8PerIsolateData.h" #include "bindings/v8/DOMDataStore.h" +#include "bindings/v8/PageScriptDebugServer.h" #include "bindings/v8/ScriptGCEvent.h" #include "bindings/v8/ScriptProfiler.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8ObjectConstructor.h" +#include "bindings/v8/V8RecursionScope.h" #include "bindings/v8/V8ScriptRunner.h" +#include "public/platform/Platform.h" +#include "wtf/MainThread.h" namespace WebCore { +static V8PerIsolateData* mainThreadPerIsolateData = 0; + +#ifndef NDEBUG +static void assertV8RecursionScope() +{ + ASSERT(V8RecursionScope::properlyUsed(v8::Isolate::GetCurrent())); +} +#endif + V8PerIsolateData::V8PerIsolateData(v8::Isolate* isolate) : m_isolate(isolate) - , m_stringCache(adoptPtr(new StringCache())) - , m_workerDomDataStore(0) - , m_hiddenPropertyName(adoptPtr(new V8HiddenPropertyName())) + , m_isolateHolder(adoptPtr(new gin::IsolateHolder(m_isolate, v8ArrayBufferAllocator()))) + , m_stringCache(adoptPtr(new StringCache(m_isolate))) + , m_hiddenValue(adoptPtr(new V8HiddenValue())) , m_constructorMode(ConstructorMode::CreateNewObject) , m_recursionLevel(0) #ifndef NDEBUG , m_internalScriptRecursionLevel(0) #endif , m_gcEventData(adoptPtr(new GCEventData())) - , m_shouldCollectGarbageSoon(false) + , m_performingMicrotaskCheckpoint(false) { +#ifndef NDEBUG + // currentThread will always be non-null in production, but can be null in Chromium unit tests. + if (blink::Platform::current()->currentThread()) + isolate->AddCallCompletedCallback(&assertV8RecursionScope); +#endif + if (isMainThread()) { + mainThreadPerIsolateData = this; + PageScriptDebugServer::setMainThreadIsolate(isolate); + } } V8PerIsolateData::~V8PerIsolateData() { + if (m_scriptRegexpScriptState) + m_scriptRegexpScriptState->disposePerContextData(); + if (isMainThread()) + mainThreadPerIsolateData = 0; } -V8PerIsolateData* V8PerIsolateData::create(v8::Isolate* isolate) +v8::Isolate* V8PerIsolateData::mainThreadIsolate() { - ASSERT(isolate); - ASSERT(!isolate->GetData(gin::kEmbedderBlink)); - V8PerIsolateData* data = new V8PerIsolateData(isolate); - isolate->SetData(gin::kEmbedderBlink, data); - return data; + ASSERT(isMainThread()); + ASSERT(mainThreadPerIsolateData); + return mainThreadPerIsolateData->isolate(); } void V8PerIsolateData::ensureInitialized(v8::Isolate* isolate) { ASSERT(isolate); - if (!isolate->GetData(gin::kEmbedderBlink)) - create(isolate); + if (!isolate->GetData(gin::kEmbedderBlink)) { + V8PerIsolateData* data = new V8PerIsolateData(isolate); + isolate->SetData(gin::kEmbedderBlink, data); + } } v8::Persistent<v8::Value>& V8PerIsolateData::ensureLiveRoot() @@ -80,76 +106,92 @@ v8::Persistent<v8::Value>& V8PerIsolateData::ensureLiveRoot() void V8PerIsolateData::dispose(v8::Isolate* isolate) { +#ifndef NDEBUG + if (blink::Platform::current()->currentThread()) + isolate->RemoveCallCompletedCallback(&assertV8RecursionScope); +#endif void* data = isolate->GetData(gin::kEmbedderBlink); delete static_cast<V8PerIsolateData*>(data); isolate->SetData(gin::kEmbedderBlink, 0); } -v8::Handle<v8::FunctionTemplate> V8PerIsolateData::toStringTemplate() +V8PerIsolateData::DOMTemplateMap& V8PerIsolateData::currentDOMTemplateMap() { - if (m_toStringTemplate.isEmpty()) - m_toStringTemplate.set(m_isolate, v8::FunctionTemplate::New(m_isolate, constructorOfToString)); - return m_toStringTemplate.newLocal(m_isolate); + if (DOMWrapperWorld::current(m_isolate).isMainWorld()) + return m_domTemplateMapForMainWorld; + return m_domTemplateMapForNonMainWorld; } -v8::Handle<v8::FunctionTemplate> V8PerIsolateData::privateTemplate(WrapperWorldType currentWorldType, void* privatePointer, v8::FunctionCallback callback, v8::Handle<v8::Value> data, v8::Handle<v8::Signature> signature, int length) +v8::Handle<v8::FunctionTemplate> V8PerIsolateData::domTemplate(void* domTemplateKey, v8::FunctionCallback callback, v8::Handle<v8::Value> data, v8::Handle<v8::Signature> signature, int length) { - TemplateMap& templates = templateMap(currentWorldType); - TemplateMap::iterator result = templates.find(privatePointer); - if (result != templates.end()) - return result->value.newLocal(m_isolate); + DOMTemplateMap& domTemplateMap = currentDOMTemplateMap(); + DOMTemplateMap::iterator result = domTemplateMap.find(domTemplateKey); + if (result != domTemplateMap.end()) + return result->value.Get(m_isolate); + v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(m_isolate, callback, data, signature, length); - templates.add(privatePointer, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ)); + domTemplateMap.add(domTemplateKey, v8::Eternal<v8::FunctionTemplate>(m_isolate, templ)); return templ; } -v8::Handle<v8::FunctionTemplate> V8PerIsolateData::privateTemplateIfExists(WrapperWorldType currentWorldType, void* privatePointer) +v8::Handle<v8::FunctionTemplate> V8PerIsolateData::existingDOMTemplate(void* domTemplateKey) { - TemplateMap& templates = templateMap(currentWorldType); - TemplateMap::iterator result = templates.find(privatePointer); - if (result != templates.end()) - return result->value.newLocal(m_isolate); + DOMTemplateMap& domTemplateMap = currentDOMTemplateMap(); + DOMTemplateMap::iterator result = domTemplateMap.find(domTemplateKey); + if (result != domTemplateMap.end()) + return result->value.Get(m_isolate); return v8::Local<v8::FunctionTemplate>(); } -void V8PerIsolateData::setPrivateTemplate(WrapperWorldType currentWorldType, void* privatePointer, v8::Handle<v8::FunctionTemplate> templ) +void V8PerIsolateData::setDOMTemplate(void* domTemplateKey, v8::Handle<v8::FunctionTemplate> templ) { - templateMap(currentWorldType).add(privatePointer, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ)); + currentDOMTemplateMap().add(domTemplateKey, v8::Eternal<v8::FunctionTemplate>(m_isolate, v8::Local<v8::FunctionTemplate>(templ))); } -v8::Handle<v8::FunctionTemplate> V8PerIsolateData::rawDOMTemplate(const WrapperTypeInfo* info, WrapperWorldType currentWorldType) +v8::Local<v8::Context> V8PerIsolateData::ensureScriptRegexpContext() { - TemplateMap& templates = rawDOMTemplateMap(currentWorldType); - TemplateMap::iterator result = templates.find(info); - if (result != templates.end()) - return result->value.newLocal(m_isolate); - - v8::EscapableHandleScope handleScope(m_isolate); - v8::Local<v8::FunctionTemplate> templ = createRawTemplate(m_isolate); - templates.add(info, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ)); - return handleScope.Escape(templ); + if (!m_scriptRegexpScriptState) { + v8::Local<v8::Context> context(v8::Context::New(m_isolate)); + m_scriptRegexpScriptState = ScriptState::create(context, DOMWrapperWorld::create()); + } + return m_scriptRegexpScriptState->context(); } -v8::Local<v8::Context> V8PerIsolateData::ensureRegexContext() +bool V8PerIsolateData::hasInstance(const WrapperTypeInfo* info, v8::Handle<v8::Value> value) { - if (m_regexContext.isEmpty()) { - v8::HandleScope handleScope(m_isolate); - m_regexContext.set(m_isolate, v8::Context::New(m_isolate)); - } - return m_regexContext.newLocal(m_isolate); + return hasInstance(info, value, m_domTemplateMapForMainWorld) + || hasInstance(info, value, m_domTemplateMapForNonMainWorld); } -bool V8PerIsolateData::hasInstance(const WrapperTypeInfo* info, v8::Handle<v8::Value> value, WrapperWorldType currentWorldType) +bool V8PerIsolateData::hasInstance(const WrapperTypeInfo* info, v8::Handle<v8::Value> value, DOMTemplateMap& domTemplateMap) { - TemplateMap& templates = rawDOMTemplateMap(currentWorldType); - TemplateMap::iterator result = templates.find(info); - if (result == templates.end()) + DOMTemplateMap::iterator result = domTemplateMap.find(info); + if (result == domTemplateMap.end()) return false; - v8::HandleScope handleScope(m_isolate); - return result->value.newLocal(m_isolate)->HasInstance(value); + v8::Handle<v8::FunctionTemplate> templ = result->value.Get(m_isolate); + return templ->HasInstance(value); } -void V8PerIsolateData::constructorOfToString(const v8::FunctionCallbackInfo<v8::Value>& info) +v8::Handle<v8::Object> V8PerIsolateData::findInstanceInPrototypeChain(const WrapperTypeInfo* info, v8::Handle<v8::Value> value) +{ + v8::Handle<v8::Object> wrapper = findInstanceInPrototypeChain(info, value, m_domTemplateMapForMainWorld); + if (!wrapper.IsEmpty()) + return wrapper; + return findInstanceInPrototypeChain(info, value, m_domTemplateMapForNonMainWorld); +} + +v8::Handle<v8::Object> V8PerIsolateData::findInstanceInPrototypeChain(const WrapperTypeInfo* info, v8::Handle<v8::Value> value, DOMTemplateMap& domTemplateMap) +{ + if (value.IsEmpty() || !value->IsObject()) + return v8::Handle<v8::Object>(); + DOMTemplateMap::iterator result = domTemplateMap.find(info); + if (result == domTemplateMap.end()) + return v8::Handle<v8::Object>(); + v8::Handle<v8::FunctionTemplate> templ = result->value.Get(m_isolate); + return v8::Handle<v8::Object>::Cast(value)->FindInstanceInPrototypeChain(templ); +} + +static void constructorOfToString(const v8::FunctionCallbackInfo<v8::Value>& info) { // The DOM constructors' toString functions grab the current toString // for Functions by taking the toString function of itself and then @@ -164,7 +206,14 @@ void V8PerIsolateData::constructorOfToString(const v8::FunctionCallbackInfo<v8:: v8SetReturnValue(info, v8::String::Empty(info.GetIsolate())); return; } - v8SetReturnValue(info, V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function>::Cast(value), info.This(), 0, 0, v8::Isolate::GetCurrent())); + v8SetReturnValue(info, V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function>::Cast(value), info.This(), 0, 0, info.GetIsolate())); +} + +v8::Handle<v8::FunctionTemplate> V8PerIsolateData::toStringTemplate() +{ + if (m_toStringTemplate.isEmpty()) + m_toStringTemplate.set(m_isolate, v8::FunctionTemplate::New(m_isolate, constructorOfToString)); + return m_toStringTemplate.newLocal(m_isolate); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.h b/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.h index bfe9f5a636f..ead107cfd1f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.h @@ -27,9 +27,11 @@ #define V8PerIsolateData_h #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/UnsafePersistent.h" +#include "bindings/v8/ScriptState.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/WrapperTypeInfo.h" #include "gin/public/gin_embedders.h" +#include "gin/public/isolate_holder.h" #include <v8.h> #include "wtf/Forward.h" #include "wtf/HashMap.h" @@ -41,21 +43,15 @@ namespace WebCore { class DOMDataStore; class GCEventData; class StringCache; -class V8HiddenPropertyName; struct WrapperTypeInfo; class ExternalStringVisitor; -typedef WTF::Vector<DOMDataStore*> DOMDataList; +typedef WTF::Vector<DOMDataStore*> DOMDataStoreList; class V8PerIsolateData { public: - static V8PerIsolateData* create(v8::Isolate*); static void ensureInitialized(v8::Isolate*); - static V8PerIsolateData* current() - { - return from(v8::Isolate::GetCurrent()); - } static V8PerIsolateData* from(v8::Isolate* isolate) { ASSERT(isolate); @@ -63,57 +59,23 @@ public: return static_cast<V8PerIsolateData*>(isolate->GetData(gin::kEmbedderBlink)); } static void dispose(v8::Isolate*); + static v8::Isolate* mainThreadIsolate(); - typedef HashMap<const void*, UnsafePersistent<v8::FunctionTemplate> > TemplateMap; - - TemplateMap& rawDOMTemplateMap(WrapperWorldType worldType) - { - if (worldType == MainWorld) - return m_rawDOMTemplatesForMainWorld; - return m_rawDOMTemplatesForNonMainWorld; - } - - TemplateMap& templateMap(WrapperWorldType worldType) - { - if (worldType == MainWorld) - return m_templatesForMainWorld; - return m_templatesForNonMainWorld; - } + v8::Isolate* isolate() { return m_isolate; } v8::Handle<v8::FunctionTemplate> toStringTemplate(); - v8::Handle<v8::FunctionTemplate> lazyEventListenerToStringTemplate() - { - return v8::Local<v8::FunctionTemplate>::New(m_isolate, m_lazyEventListenerToStringTemplate); - } StringCache* stringCache() { return m_stringCache.get(); } v8::Persistent<v8::Value>& ensureLiveRoot(); - DOMDataList& allStores() { return m_domDataList; } - - V8HiddenPropertyName* hiddenPropertyName() { return m_hiddenPropertyName.get(); } - - void registerDOMDataStore(DOMDataStore* domDataStore) - { - ASSERT(m_domDataList.find(domDataStore) == kNotFound); - m_domDataList.append(domDataStore); - } - - void unregisterDOMDataStore(DOMDataStore* domDataStore) - { - ASSERT(m_domDataList.find(domDataStore) != kNotFound); - m_domDataList.remove(m_domDataList.find(domDataStore)); - } - - // DOMDataStore is owned outside V8PerIsolateData. - DOMDataStore* workerDOMDataStore() { return m_workerDomDataStore; } - void setWorkerDOMDataStore(DOMDataStore* store) { m_workerDomDataStore = store; } - int recursionLevel() const { return m_recursionLevel; } int incrementRecursionLevel() { return ++m_recursionLevel; } int decrementRecursionLevel() { return --m_recursionLevel; } + bool performingMicrotaskCheckpoint() const { return m_performingMicrotaskCheckpoint; } + void setPerformingMicrotaskCheckpoint(bool performingMicrotaskCheckpoint) { m_performingMicrotaskCheckpoint = performingMicrotaskCheckpoint; } + #ifndef NDEBUG int internalScriptRecursionLevel() const { return m_internalScriptRecursionLevel; } int incrementInternalScriptRecursionLevel() { return ++m_internalScriptRecursionLevel; } @@ -121,24 +83,16 @@ public: #endif GCEventData* gcEventData() { return m_gcEventData.get(); } + V8HiddenValue* hiddenValue() { return m_hiddenValue.get(); } - // Gives the system a hint that we should request garbage collection - // upon the next close or navigation event, because some expensive - // objects have been allocated that we want to take every opportunity - // to collect. - void setShouldCollectGarbageSoon() { m_shouldCollectGarbageSoon = true; } - void clearShouldCollectGarbageSoon() { m_shouldCollectGarbageSoon = false; } - bool shouldCollectGarbageSoon() const { return m_shouldCollectGarbageSoon; } - - v8::Handle<v8::FunctionTemplate> privateTemplate(WrapperWorldType, void* privatePointer, v8::FunctionCallback = 0, v8::Handle<v8::Value> data = v8::Handle<v8::Value>(), v8::Handle<v8::Signature> = v8::Handle<v8::Signature>(), int length = 0); - v8::Handle<v8::FunctionTemplate> privateTemplateIfExists(WrapperWorldType, void* privatePointer); - void setPrivateTemplate(WrapperWorldType, void* privatePointer, v8::Handle<v8::FunctionTemplate>); - - v8::Handle<v8::FunctionTemplate> rawDOMTemplate(const WrapperTypeInfo*, WrapperWorldType); + v8::Handle<v8::FunctionTemplate> domTemplate(void* domTemplateKey, v8::FunctionCallback = 0, v8::Handle<v8::Value> data = v8::Handle<v8::Value>(), v8::Handle<v8::Signature> = v8::Handle<v8::Signature>(), int length = 0); + v8::Handle<v8::FunctionTemplate> existingDOMTemplate(void* domTemplateKey); + void setDOMTemplate(void* domTemplateKey, v8::Handle<v8::FunctionTemplate>); - bool hasInstance(const WrapperTypeInfo*, v8::Handle<v8::Value>, WrapperWorldType); + bool hasInstance(const WrapperTypeInfo*, v8::Handle<v8::Value>); + v8::Handle<v8::Object> findInstanceInPrototypeChain(const WrapperTypeInfo*, v8::Handle<v8::Value>); - v8::Local<v8::Context> ensureRegexContext(); + v8::Local<v8::Context> ensureScriptRegexpContext(); const char* previousSamplingState() const { return m_previousSamplingState; } void setPreviousSamplingState(const char* name) { m_previousSamplingState = name; } @@ -146,23 +100,21 @@ public: private: explicit V8PerIsolateData(v8::Isolate*); ~V8PerIsolateData(); - static void constructorOfToString(const v8::FunctionCallbackInfo<v8::Value>&); + + typedef HashMap<const void*, v8::Eternal<v8::FunctionTemplate> > DOMTemplateMap; + DOMTemplateMap& currentDOMTemplateMap(); + bool hasInstance(const WrapperTypeInfo*, v8::Handle<v8::Value>, DOMTemplateMap&); + v8::Handle<v8::Object> findInstanceInPrototypeChain(const WrapperTypeInfo*, v8::Handle<v8::Value>, DOMTemplateMap&); v8::Isolate* m_isolate; - TemplateMap m_rawDOMTemplatesForMainWorld; - TemplateMap m_rawDOMTemplatesForNonMainWorld; - TemplateMap m_templatesForMainWorld; - TemplateMap m_templatesForNonMainWorld; + OwnPtr<gin::IsolateHolder> m_isolateHolder; + DOMTemplateMap m_domTemplateMapForMainWorld; + DOMTemplateMap m_domTemplateMapForNonMainWorld; ScopedPersistent<v8::FunctionTemplate> m_toStringTemplate; - v8::Persistent<v8::FunctionTemplate> m_lazyEventListenerToStringTemplate; OwnPtr<StringCache> m_stringCache; - - Vector<DOMDataStore*> m_domDataList; - DOMDataStore* m_workerDomDataStore; - - OwnPtr<V8HiddenPropertyName> m_hiddenPropertyName; + OwnPtr<V8HiddenValue> m_hiddenValue; ScopedPersistent<v8::Value> m_liveRoot; - ScopedPersistent<v8::Context> m_regexContext; + RefPtr<ScriptState> m_scriptRegexpScriptState; const char* m_previousSamplingState; @@ -175,7 +127,7 @@ private: int m_internalScriptRecursionLevel; #endif OwnPtr<GCEventData> m_gcEventData; - bool m_shouldCollectGarbageSoon; + bool m_performingMicrotaskCheckpoint; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8PersistentValueMap.h b/chromium/third_party/WebKit/Source/bindings/v8/V8PersistentValueMap.h new file mode 100644 index 00000000000..0fa2ac2c902 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PersistentValueMap.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8PersistentValueMap_h +#define V8PersistentValueMap_h + +#include "wtf/HashMap.h" +#include <v8-util.h> +#include <v8.h> + +namespace WebCore { + +/** + * A Traits class for v8::PersistentValueMap that uses wtf/HashMap as a + * backing store. + * + * The parameter is_weak will determine whether the references are 'weak'. + * If so, entries will be removed from the map as the weak references are + * collected. + */ +template<class KeyType, class ValueType, bool is_weak> +class V8PersistentValueMapTraits { +public: + // Map traits: + typedef HashMap<KeyType, v8::PersistentContainerValue> Impl; + typedef typename Impl::iterator Iterator; + static size_t Size(const Impl* impl) { return impl->size(); } + static bool Empty(Impl* impl) { return impl->isEmpty(); } + static void Swap(Impl& impl, Impl& other) { impl.swap(other); } + static Iterator Begin(Impl* impl) { return impl->begin(); } + static Iterator End(Impl* impl) { return impl->end(); } + static v8::PersistentContainerValue Value(Iterator& iter) + { + return iter->value; + } + static KeyType Key(Iterator& iter) { return iter->key; } + static v8::PersistentContainerValue Set( + Impl* impl, KeyType key, v8::PersistentContainerValue value) + { + v8::PersistentContainerValue oldValue = Get(impl, key); + impl->set(key, value); + return oldValue; + } + static v8::PersistentContainerValue Get(const Impl* impl, KeyType key) + { + return impl->get(key); + } + + static v8::PersistentContainerValue Remove(Impl* impl, KeyType key) + { + return impl->take(key); + } + + // Weak traits: + static const v8::PersistentContainerCallbackType kCallbackType = is_weak ? v8::kWeak : v8::kNotWeak; + typedef v8::PersistentValueMap<KeyType, ValueType, V8PersistentValueMapTraits<KeyType, ValueType, is_weak> > MapType; + + typedef void WeakCallbackDataType; + + static WeakCallbackDataType* WeakCallbackParameter(MapType* map, KeyType key, const v8::Local<ValueType>& value) + { + return 0; + } + + static void DisposeCallbackData(WeakCallbackDataType* callbackData) + { + } + + static MapType* MapFromWeakCallbackData( + const v8::WeakCallbackData<ValueType, WeakCallbackDataType>& data) + { + return 0; + } + + static KeyType KeyFromWeakCallbackData( + const v8::WeakCallbackData<ValueType, WeakCallbackDataType>& data) + { + return KeyType(); + } + + // Dispose traits: + static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<ValueType> value, KeyType key) { } +}; + +/** + * A map for safely storing persistent V8 values, based on + * v8::PersistentValueMap. + * + * If is_weak is set, values will be held weakly and map entries will be + * removed as their values are being collected. + */ +template<class KeyType, class ValueType, bool is_weak = true> +class V8PersistentValueMap : public v8::PersistentValueMap<KeyType, ValueType, V8PersistentValueMapTraits<KeyType, ValueType, is_weak> > { +public: + typedef V8PersistentValueMapTraits<KeyType, ValueType, is_weak> Traits; + explicit V8PersistentValueMap(v8::Isolate* isolate) : v8::PersistentValueMap<KeyType, ValueType, Traits>(isolate) { } +}; + +} // namespace WebCore + +#endif // V8PersistentValueMap_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeListCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8PersistentValueVector.h index 341f1c23d5d..02f8314e937 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeListCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PersistentValueVector.h @@ -28,33 +28,50 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "V8NodeList.h" +#ifndef V8PersistentValueVector_h +#define V8PersistentValueVector_h -#include "V8Node.h" -#include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8GCController.h" -#include "core/dom/LiveNodeList.h" -#include "core/dom/NodeList.h" -#include "wtf/RefPtr.h" -#include "wtf/StdLibExtras.h" +#include "wtf/Vector.h" +#include <v8-util.h> +#include <v8.h> namespace WebCore { -void V8NodeList::visitDOMWrapper(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) -{ - NodeList* impl = static_cast<NodeList*>(object); - if (!impl->isLiveNodeList()) { - setObjectGroup(object, wrapper, isolate); - return; +class WTFVectorPersistentValueVectorTraits { +public: + typedef Vector<v8::PersistentContainerValue> Impl; + static void Append(Impl* impl, v8::PersistentContainerValue value) + { + impl->append(value); } - Node* owner = static_cast<LiveNodeList*>(impl)->ownerNode(); - if (!owner) { - setObjectGroup(object, wrapper, isolate); - return; + static bool IsEmpty(const Impl* impl) + { + return impl->isEmpty(); } + static size_t Size(const Impl* impl) + { + return impl->size(); + } + static v8::PersistentContainerValue Get(const Impl* impl, size_t i) + { + return (i < impl->size()) ? impl->at(i) : v8::kPersistentContainerNotFound; + } + static void ReserveCapacity(Impl* impl, size_t capacity) + { + impl->reserveCapacity(capacity); + } + static void Clear(Impl* impl) + { + impl->clear(); + } +}; - setObjectGroup(V8GCController::opaqueRootForGC(owner, isolate), wrapper, isolate); -} +template<class ValueType> +class V8PersistentValueVector : public v8::PersistentValueVector<ValueType, WTFVectorPersistentValueVectorTraits> { +public: + explicit V8PersistentValueVector(v8::Isolate* isolate) : v8::PersistentValueVector<ValueType, WTFVectorPersistentValueVectorTraits>(isolate) { } +}; } // namespace WebCore + +#endif // V8PersistentValueVector_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.cpp index c08fba7c855..2519250f28f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.cpp @@ -38,14 +38,11 @@ namespace WebCore { void V8RecursionScope::didLeaveScriptContext() { - // FIXME: Instrument any work that takes place when script exits to c++ (e.g. Mutation Observers). + Microtask::performCheckpoint(); // Indexed DB requires that transactions are created with an internal |active| flag // set to true, but the flag becomes false when control returns to the event loop. - IDBPendingTransactionMonitor::deactivateNewTransactions(); - - if (m_isDocumentContext) - Microtask::performCheckpoint(); + IDBPendingTransactionMonitor::from(m_executionContext).deactivateNewTransactions(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.h b/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.h index 3bc3da7d024..a73d93a8dc0 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.h @@ -33,7 +33,9 @@ #include "bindings/v8/V8PerIsolateData.h" #include "core/dom/ExecutionContext.h" +#include "core/dom/ScriptForbiddenScope.h" #include "wtf/Noncopyable.h" +#include <v8.h> namespace WebCore { @@ -57,51 +59,66 @@ namespace WebCore { class V8RecursionScope { WTF_MAKE_NONCOPYABLE(V8RecursionScope); public: - explicit V8RecursionScope(ExecutionContext* context) - : m_isDocumentContext(context && context->isDocument()) + V8RecursionScope(v8::Isolate* isolate, ExecutionContext* context) + : m_isolate(isolate) + , m_executionContext(*context) { - V8PerIsolateData::current()->incrementRecursionLevel(); + V8PerIsolateData::from(m_isolate)->incrementRecursionLevel(); + ASSERT(!ScriptForbiddenScope::isScriptForbidden()); + // If you want V8 to autorun microtasks, this class needs to have a + // v8::Isolate::SuppressMicrotaskExecutionScope member. + ASSERT(!isolate->WillAutorunMicrotasks()); } ~V8RecursionScope() { - if (!V8PerIsolateData::current()->decrementRecursionLevel()) + if (!V8PerIsolateData::from(m_isolate)->decrementRecursionLevel()) didLeaveScriptContext(); } - static int recursionLevel() + static int recursionLevel(v8::Isolate* isolate) { - return V8PerIsolateData::current()->recursionLevel(); + return V8PerIsolateData::from(isolate)->recursionLevel(); } #ifndef NDEBUG - static bool properlyUsed() + static bool properlyUsed(v8::Isolate* isolate) { - return recursionLevel() > 0 || V8PerIsolateData::current()->internalScriptRecursionLevel() > 0; + return recursionLevel(isolate) > 0 || V8PerIsolateData::from(isolate)->internalScriptRecursionLevel() > 0; } #endif class MicrotaskSuppression { public: - MicrotaskSuppression() + MicrotaskSuppression(v8::Isolate* isolate) +#ifndef NDEBUG + : m_isolate(isolate) +#endif { + ASSERT(!ScriptForbiddenScope::isScriptForbidden()); #ifndef NDEBUG - V8PerIsolateData::current()->incrementInternalScriptRecursionLevel(); + V8PerIsolateData::from(m_isolate)->incrementInternalScriptRecursionLevel(); #endif } ~MicrotaskSuppression() { #ifndef NDEBUG - V8PerIsolateData::current()->decrementInternalScriptRecursionLevel(); + V8PerIsolateData::from(m_isolate)->decrementInternalScriptRecursionLevel(); #endif } + + private: +#ifndef NDEBUG + v8::Isolate* m_isolate; +#endif }; private: void didLeaveScriptContext(); - bool m_isDocumentContext; + v8::Isolate* m_isolate; + ExecutionContext& m_executionContext; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.cpp index ed6a1730117..625fddf8095 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "bindings/v8/V8ScriptRunner.h" +#include "bindings/v8/ScriptSourceCode.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8GCController.h" #include "bindings/v8/V8RecursionScope.h" @@ -36,70 +37,74 @@ namespace WebCore { -PassOwnPtr<v8::ScriptData> V8ScriptRunner::precompileScript(v8::Handle<v8::String> code, ScriptResource* resource) +v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& source, v8::Isolate* isolate, AccessControlStatus corsStatus) +{ + return compileScript(v8String(isolate, source.source()), source.url(), source.startPosition(), source.resource(), isolate, corsStatus); +} + +v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition& scriptStartPosition, ScriptResource* resource, v8::Isolate* isolate, AccessControlStatus corsStatus) { - TRACE_EVENT0("v8", "v8.compile"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Compile"); // A pseudo-randomly chosen ID used to store and retrieve V8 ScriptData from // the ScriptResource. If the format changes, this ID should be changed too. static const unsigned dataTypeID = 0xECC13BD7; - // Very small scripts are not worth the effort to preparse. - static const int minPreparseLength = 1024; - - if (!resource || code->Length() < minPreparseLength) - return nullptr; - - CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID); - if (cachedMetadata) - return adoptPtr(v8::ScriptData::New(cachedMetadata->data(), cachedMetadata->size())); - - OwnPtr<v8::ScriptData> scriptData = adoptPtr(v8::ScriptData::PreCompile(code)); - if (!scriptData) - return nullptr; + // Very small scripts are not worth the effort to store cached data. + static const int minLengthForCachedData = 1024; - resource->setCachedMetadata(dataTypeID, scriptData->Data(), scriptData->Length()); + TRACE_EVENT1("v8", "v8.compile", "fileName", fileName.utf8()); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Compile"); - return scriptData.release(); -} - -v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition& scriptStartPosition, v8::ScriptData* scriptData, v8::Isolate* isolate, AccessControlStatus corsStatus) -{ - TRACE_EVENT0("v8", "v8.compile"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Compile"); + // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at + // 1, whereas v8 starts at 0. v8::Handle<v8::String> name = v8String(isolate, fileName); - v8::Handle<v8::Integer> line = v8::Integer::New(scriptStartPosition.m_line.zeroBasedInt(), isolate); - v8::Handle<v8::Integer> column = v8::Integer::New(scriptStartPosition.m_column.zeroBasedInt(), isolate); + v8::Handle<v8::Integer> line = v8::Integer::New(isolate, scriptStartPosition.m_line.zeroBasedInt()); + v8::Handle<v8::Integer> column = v8::Integer::New(isolate, scriptStartPosition.m_column.zeroBasedInt()); v8::Handle<v8::Boolean> isSharedCrossOrigin = corsStatus == SharableCrossOrigin ? v8::True(isolate) : v8::False(isolate); v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin); - return v8::Script::Compile(code, &origin, scriptData); + + v8::ScriptCompiler::CompileOptions options = v8::ScriptCompiler::kNoCompileOptions; + OwnPtr<v8::ScriptCompiler::CachedData> cachedData; + if (resource) { + CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID); + if (cachedMetadata) { + // Ownership of the buffer is not transferred to CachedData. + cachedData = adoptPtr(new v8::ScriptCompiler::CachedData(reinterpret_cast<const uint8_t*>(cachedMetadata->data()), cachedMetadata->size())); + } else if (code->Length() >= minLengthForCachedData) { + options = v8::ScriptCompiler::kProduceDataToCache; + } + } + // source takes ownership of cachedData. + v8::ScriptCompiler::Source source(code, origin, cachedData.leakPtr()); + v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source, options); + if (options == v8::ScriptCompiler::kProduceDataToCache) { + const v8::ScriptCompiler::CachedData* newCachedData = source.GetCachedData(); + if (newCachedData) { + // Ownership of the buffer is not transferred; source's cachedData continues to own it. + resource->setCachedMetadata(dataTypeID, reinterpret_cast<const char*>(newCachedData->data), newCachedData->length); + } + } + return script; } v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Handle<v8::Script> script, ExecutionContext* context, v8::Isolate* isolate) { - TRACE_EVENT0("v8", "v8.run"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); if (script.IsEmpty()) return v8::Local<v8::Value>(); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); + TRACE_EVENT1("v8", "v8.run", "fileName", TRACE_STR_COPY(*v8::String::Utf8Value(script->GetUnboundScript()->GetScriptName()))); - if (V8RecursionScope::recursionLevel() >= kMaxRecursionDepth) + if (V8RecursionScope::recursionLevel(isolate) >= kMaxRecursionDepth) return handleMaxRecursionDepthExceeded(isolate); - if (handleOutOfMemory()) - return v8::Local<v8::Value>(); - RELEASE_ASSERT(!context->isIteratingOverObservers()); // Run the script and keep track of the current recursion depth. v8::Local<v8::Value> result; { - V8RecursionScope recursionScope(context); + V8RecursionScope recursionScope(isolate, context); result = script->Run(); } - if (handleOutOfMemory()) - ASSERT(result.IsEmpty()); - if (result.IsEmpty()) return v8::Local<v8::Value>(); @@ -107,95 +112,84 @@ v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Handle<v8::Script> sc return result; } -v8::Local<v8::Value> V8ScriptRunner::compileAndRunInternalScript(v8::Handle<v8::String> source, v8::Isolate* isolate, const String& fileName, const TextPosition& scriptStartPosition, v8::ScriptData* scriptData) +v8::Local<v8::Value> V8ScriptRunner::compileAndRunInternalScript(v8::Handle<v8::String> source, v8::Isolate* isolate, const String& fileName, const TextPosition& scriptStartPosition) { TRACE_EVENT0("v8", "v8.run"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); - v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, fileName, scriptStartPosition, scriptData, isolate); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); + v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, fileName, scriptStartPosition, 0, isolate); if (script.IsEmpty()) return v8::Local<v8::Value>(); - V8RecursionScope::MicrotaskSuppression recursionScope; + V8RecursionScope::MicrotaskSuppression recursionScope(isolate); v8::Local<v8::Value> result = script->Run(); crashIfV8IsDead(); return result; } -v8::Local<v8::Value> V8ScriptRunner::callFunction(v8::Handle<v8::Function> function, ExecutionContext* context, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate* isolate) +v8::Local<v8::Value> V8ScriptRunner::callFunction(v8::Handle<v8::Function> function, ExecutionContext* context, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> args[], v8::Isolate* isolate) { TRACE_EVENT0("v8", "v8.callFunction"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); - if (V8RecursionScope::recursionLevel() >= kMaxRecursionDepth) + if (V8RecursionScope::recursionLevel(isolate) >= kMaxRecursionDepth) return handleMaxRecursionDepthExceeded(isolate); RELEASE_ASSERT(!context->isIteratingOverObservers()); - V8RecursionScope recursionScope(context); - v8::Local<v8::Value> result = function->Call(receiver, argc, info); + V8RecursionScope recursionScope(isolate, context); + v8::Local<v8::Value> result = function->Call(receiver, argc, args); crashIfV8IsDead(); return result; } -v8::Local<v8::Value> V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate* isolate) +v8::Local<v8::Value> V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> args[], v8::Isolate* isolate) { TRACE_EVENT0("v8", "v8.callFunction"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); - V8RecursionScope::MicrotaskSuppression recursionScope; - v8::Local<v8::Value> result = function->Call(receiver, argc, info); - crashIfV8IsDead(); - return result; -} - -v8::Local<v8::Value> V8ScriptRunner::callAsFunction(v8::Handle<v8::Object> object, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[]) -{ - TRACE_EVENT0("v8", "v8.callFunction"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); - - V8RecursionScope::MicrotaskSuppression recursionScope; - v8::Local<v8::Value> result = object->CallAsFunction(receiver, argc, info); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); + V8RecursionScope::MicrotaskSuppression recursionScope(isolate); + v8::Local<v8::Value> result = function->Call(receiver, argc, args); crashIfV8IsDead(); return result; } -v8::Local<v8::Value> V8ScriptRunner::callAsConstructor(v8::Handle<v8::Object> object, int argc, v8::Handle<v8::Value> info[]) +v8::Local<v8::Value> V8ScriptRunner::callAsFunction(v8::Isolate* isolate, v8::Handle<v8::Object> object, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> args[]) { TRACE_EVENT0("v8", "v8.callFunction"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); - V8RecursionScope::MicrotaskSuppression recursionScope; - v8::Local<v8::Value> result = object->CallAsConstructor(argc, info); + V8RecursionScope::MicrotaskSuppression recursionScope(isolate); + v8::Local<v8::Value> result = object->CallAsFunction(receiver, argc, args); crashIfV8IsDead(); return result; } -v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Handle<v8::ObjectTemplate> objectTemplate) +v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Isolate* isolate, v8::Handle<v8::ObjectTemplate> objectTemplate) { TRACE_EVENT0("v8", "v8.newInstance"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); - V8RecursionScope::MicrotaskSuppression scope; + V8RecursionScope::MicrotaskSuppression scope(isolate); v8::Local<v8::Object> result = objectTemplate->NewInstance(); crashIfV8IsDead(); return result; } -v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) +v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Isolate* isolate, v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) { TRACE_EVENT0("v8", "v8.newInstance"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); - V8RecursionScope::MicrotaskSuppression scope; + V8RecursionScope::MicrotaskSuppression scope(isolate); v8::Local<v8::Object> result = function->NewInstance(argc, argv); crashIfV8IsDead(); return result; } -v8::Local<v8::Object> V8ScriptRunner::instantiateObjectInDocument(v8::Handle<v8::Function> function, ExecutionContext* context, int argc, v8::Handle<v8::Value> argv[]) +v8::Local<v8::Object> V8ScriptRunner::instantiateObjectInDocument(v8::Isolate* isolate, v8::Handle<v8::Function> function, ExecutionContext* context, int argc, v8::Handle<v8::Value> argv[]) { TRACE_EVENT0("v8", "v8.newInstance"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); - V8RecursionScope scope(context); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); + V8RecursionScope scope(isolate, context); v8::Local<v8::Object> result = function->NewInstance(argc, argv); crashIfV8IsDead(); return result; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.h b/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.h index b36102f20ba..368401be41f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.h @@ -35,23 +35,23 @@ namespace WebCore { class ScriptResource; +class ScriptSourceCode; class ExecutionContext; class V8ScriptRunner { public: // For the following methods, the caller sites have to hold // a HandleScope and a ContextScope. - static PassOwnPtr<v8::ScriptData> precompileScript(v8::Handle<v8::String>, ScriptResource*); - static v8::Local<v8::Script> compileScript(v8::Handle<v8::String>, const String&, const TextPosition&, v8::ScriptData*, v8::Isolate*, AccessControlStatus = SharableCrossOrigin); + static v8::Local<v8::Script> compileScript(const ScriptSourceCode&, v8::Isolate*, AccessControlStatus = SharableCrossOrigin); + static v8::Local<v8::Script> compileScript(v8::Handle<v8::String>, const String& fileName, const TextPosition&, ScriptResource*, v8::Isolate*, AccessControlStatus = SharableCrossOrigin); static v8::Local<v8::Value> runCompiledScript(v8::Handle<v8::Script>, ExecutionContext*, v8::Isolate*); - static v8::Local<v8::Value> compileAndRunInternalScript(v8::Handle<v8::String>, v8::Isolate*, const String& = String(), const TextPosition& = TextPosition(), v8::ScriptData* = 0); + static v8::Local<v8::Value> compileAndRunInternalScript(v8::Handle<v8::String>, v8::Isolate*, const String& = String(), const TextPosition& = TextPosition()); static v8::Local<v8::Value> callInternalFunction(v8::Handle<v8::Function>, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate*); static v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, ExecutionContext*, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate*); - static v8::Local<v8::Value> callAsFunction(v8::Handle<v8::Object>, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[]); - static v8::Local<v8::Value> callAsConstructor(v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> info[]); - static v8::Local<v8::Object> instantiateObject(v8::Handle<v8::ObjectTemplate>); - static v8::Local<v8::Object> instantiateObject(v8::Handle<v8::Function>, int argc = 0, v8::Handle<v8::Value> argv[] = 0); - static v8::Local<v8::Object> instantiateObjectInDocument(v8::Handle<v8::Function>, ExecutionContext*, int argc = 0, v8::Handle<v8::Value> argv[] = 0); + static v8::Local<v8::Value> callAsFunction(v8::Isolate*, v8::Handle<v8::Object>, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[]); + static v8::Local<v8::Object> instantiateObject(v8::Isolate*, v8::Handle<v8::ObjectTemplate>); + static v8::Local<v8::Object> instantiateObject(v8::Isolate*, v8::Handle<v8::Function>, int argc = 0, v8::Handle<v8::Value> argv[] = 0); + static v8::Local<v8::Object> instantiateObjectInDocument(v8::Isolate*, v8::Handle<v8::Function>, ExecutionContext*, int argc = 0, v8::Handle<v8::Value> argv[] = 0); }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.cpp index bce62d4c2fa..3b76e8243f9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.cpp @@ -32,27 +32,9 @@ namespace WebCore { -WebCoreStringResourceBase* WebCoreStringResourceBase::toWebCoreStringResourceBase(v8::Handle<v8::String> string) -{ - v8::String::Encoding encoding; - v8::String::ExternalStringResourceBase* resource = string->GetExternalStringResourceBase(&encoding); - if (!resource) - return 0; - if (encoding == v8::String::ONE_BYTE_ENCODING) - return static_cast<WebCoreStringResource8*>(resource); - return static_cast<WebCoreStringResource16*>(resource); -} - -void WebCoreStringResourceBase::visitStrings(ExternalStringVisitor* visitor) -{ - visitor->visitJSExternalString(m_plainString.impl()); - if (m_plainString.impl() != m_atomicString.impl() && !m_atomicString.isNull()) - visitor->visitJSExternalString(m_atomicString.impl()); -} - template<class StringClass> struct StringTraits { static const StringClass& fromStringResource(WebCoreStringResourceBase*); - template<bool oneByte> + template <typename V8StringTrait> static StringClass fromV8String(v8::Handle<v8::String>, int); }; @@ -62,7 +44,7 @@ struct StringTraits<String> { { return resource->webcoreString(); } - template<bool oneByte> + template <typename V8StringTrait> static String fromV8String(v8::Handle<v8::String>, int); }; @@ -72,59 +54,49 @@ struct StringTraits<AtomicString> { { return resource->atomicString(); } - template<bool oneByte> + template <typename V8StringTrait> static AtomicString fromV8String(v8::Handle<v8::String>, int); }; -template<> -String StringTraits<String>::fromV8String<false>(v8::Handle<v8::String> v8String, int length) -{ - ASSERT(v8String->Length() == length); - UChar* buffer; - String result = String::createUninitialized(length, buffer); - v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); - return result; -} +struct V8StringTwoBytesTrait { + typedef UChar CharType; + ALWAYS_INLINE static void write(v8::Handle<v8::String> v8String, CharType* buffer, int length) + { + v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); + } +}; -template<> -AtomicString StringTraits<AtomicString>::fromV8String<false>(v8::Handle<v8::String> v8String, int length) -{ - ASSERT(v8String->Length() == length); - static const int inlineBufferSize = 16; - if (length <= inlineBufferSize) { - UChar inlineBuffer[inlineBufferSize]; - v8String->Write(reinterpret_cast<uint16_t*>(inlineBuffer), 0, length); - return AtomicString(inlineBuffer, length); +struct V8StringOneByteTrait { + typedef LChar CharType; + ALWAYS_INLINE static void write(v8::Handle<v8::String> v8String, CharType* buffer, int length) + { + v8String->WriteOneByte(buffer, 0, length); } - UChar* buffer; - String result = String::createUninitialized(length, buffer); - v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); - return AtomicString(result); -} +}; -template<> -String StringTraits<String>::fromV8String<true>(v8::Handle<v8::String> v8String, int length) +template <typename V8StringTrait> +String StringTraits<String>::fromV8String(v8::Handle<v8::String> v8String, int length) { ASSERT(v8String->Length() == length); - LChar* buffer; + typename V8StringTrait::CharType* buffer; String result = String::createUninitialized(length, buffer); - v8String->WriteOneByte(buffer, 0, length); + V8StringTrait::write(v8String, buffer, length); return result; } -template<> -AtomicString StringTraits<AtomicString>::fromV8String<true>(v8::Handle<v8::String> v8String, int length) +template <typename V8StringTrait> +AtomicString StringTraits<AtomicString>::fromV8String(v8::Handle<v8::String> v8String, int length) { ASSERT(v8String->Length() == length); - static const int inlineBufferSize = 32; + static const int inlineBufferSize = 32 / sizeof(typename V8StringTrait::CharType); if (length <= inlineBufferSize) { - LChar inlineBuffer[inlineBufferSize]; - v8String->WriteOneByte(inlineBuffer, 0, length); + typename V8StringTrait::CharType inlineBuffer[inlineBufferSize]; + V8StringTrait::write(v8String, inlineBuffer, length); return AtomicString(inlineBuffer, length); } - LChar* buffer; + typename V8StringTrait::CharType* buffer; String string = String::createUninitialized(length, buffer); - v8String->WriteOneByte(buffer, 0, length); + V8StringTrait::write(v8String, buffer, length); return AtomicString(string); } @@ -132,7 +104,6 @@ template<typename StringType> StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external) { { - // A lot of WebCoreStringResourceBase::toWebCoreStringResourceBase is copied here by hand for performance reasons. // This portion of this function is very hot in certain Dromeao benchmarks. v8::String::Encoding encoding; v8::String::ExternalStringResourceBase* resource = v8String->GetExternalStringResourceBase(&encoding); @@ -151,7 +122,7 @@ StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode return StringType(""); bool oneByte = v8String->ContainsOnlyOneByte(); - StringType result(oneByte ? StringTraits<StringType>::template fromV8String<true>(v8String, length) : StringTraits<StringType>::template fromV8String<false>(v8String, length)); + StringType result(oneByte ? StringTraits<StringType>::template fromV8String<V8StringOneByteTrait>(v8String, length) : StringTraits<StringType>::template fromV8String<V8StringTwoBytesTrait>(v8String, length)); if (external != Externalize || !v8String->CanMakeExternal()) return result; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.h b/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.h index b8b57944a47..69f849b31e9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.h @@ -39,8 +39,6 @@ class ExternalStringVisitor; // to manage the life-cycle of the underlying buffer of the external string. class WebCoreStringResourceBase { public: - static WebCoreStringResourceBase* toWebCoreStringResourceBase(v8::Handle<v8::String>); - explicit WebCoreStringResourceBase(const String& string) : m_plainString(string) { @@ -89,8 +87,6 @@ public: return m_atomicString; } - void visitStrings(ExternalStringVisitor*); - protected: // A shallow copy of the string. Keeps the string buffer alive until the V8 engine garbage collects it. String m_plainString; @@ -111,7 +107,7 @@ private: #endif }; -class WebCoreStringResource16 : public WebCoreStringResourceBase, public v8::String::ExternalStringResource { +class WebCoreStringResource16 FINAL : public WebCoreStringResourceBase, public v8::String::ExternalStringResource { public: explicit WebCoreStringResource16(const String& string) : WebCoreStringResourceBase(string) @@ -132,7 +128,7 @@ public: } }; -class WebCoreStringResource8 : public WebCoreStringResourceBase, public v8::String::ExternalAsciiStringResource { +class WebCoreStringResource8 FINAL : public WebCoreStringResourceBase, public v8::String::ExternalAsciiStringResource { public: explicit WebCoreStringResource8(const String& string) : WebCoreStringResourceBase(string) @@ -173,23 +169,37 @@ enum V8StringResourceMode { template <V8StringResourceMode Mode = DefaultMode> class V8StringResource { public: + V8StringResource() + : m_mode(Externalize) + { + } + V8StringResource(v8::Handle<v8::Value> object) : m_v8Object(object) , m_mode(Externalize) - , m_string() { } - bool prepare(); - operator String() const { return toString<String>(); } - operator AtomicString() const { return toString<AtomicString>(); } + void operator=(v8::Handle<v8::Value> object) + { + m_v8Object = object; + } -private: - bool prepareBase() + void operator=(const String& string) + { + setString(string); + } + + bool prepare() { if (m_v8Object.IsEmpty()) return true; + if (!isValid()) { + setString(String()); + return true; + } + if (LIKELY(m_v8Object->IsString())) return true; @@ -208,6 +218,11 @@ private: } return true; } + operator String() const { return toString<String>(); } + operator AtomicString() const { return toString<AtomicString>(); } + +private: + bool isValid() const; void setString(const String& string) { @@ -229,27 +244,19 @@ private: String m_string; }; -template<> inline bool V8StringResource<DefaultMode>::prepare() +template<> inline bool V8StringResource<DefaultMode>::isValid() const { - return prepareBase(); + return true; } -template<> inline bool V8StringResource<WithNullCheck>::prepare() +template<> inline bool V8StringResource<WithNullCheck>::isValid() const { - if (m_v8Object.IsEmpty() || m_v8Object->IsNull()) { - setString(String()); - return true; - } - return prepareBase(); + return !m_v8Object->IsNull(); } -template<> inline bool V8StringResource<WithUndefinedOrNullCheck>::prepare() +template<> inline bool V8StringResource<WithUndefinedOrNullCheck>::isValid() const { - if (m_v8Object.IsEmpty() || m_v8Object->IsNull() || m_v8Object->IsUndefined()) { - setString(String()); - return true; - } - return prepareBase(); + return !m_v8Object->IsNull() && !m_v8Object->IsUndefined(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.cpp index 0f1ffcc69d3..ae2be273cff 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.cpp @@ -25,7 +25,7 @@ #include "config.h" #include "bindings/v8/V8ThrowException.h" -#include "V8DOMException.h" +#include "bindings/core/v8/V8DOMException.h" #include "bindings/v8/V8Binding.h" #include "core/dom/DOMException.h" #include "core/dom/ExceptionCode.h" @@ -55,7 +55,7 @@ v8::Handle<v8::Value> V8ThrowException::createDOMException(int ec, const String& if (ec == TypeError) return V8ThrowException::createTypeError(sanitizedMessage, isolate); - RefPtr<DOMException> domException = DOMException::create(ec, sanitizedMessage, unsanitizedMessage); + RefPtrWillBeRawPtr<DOMException> domException = DOMException::create(ec, sanitizedMessage, unsanitizedMessage); v8::Handle<v8::Value> exception = toV8(domException, creationContext, isolate); if (exception.IsEmpty()) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.h b/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.h index 7a4d20f0609..26addf08538 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.h @@ -47,10 +47,6 @@ public: } static v8::Handle<v8::Value> createDOMException(int, const String& sanitizedMessage, const String& unsanitizedMessage, const v8::Handle<v8::Object>& creationContext, v8::Isolate*); - static v8::Handle<v8::Value> throwDOMException(int ec, const v8::Handle<v8::Object>& creationContext, v8::Isolate* isolate) - { - return throwDOMException(ec, String(), creationContext, isolate); - } static v8::Handle<v8::Value> throwDOMException(int ec, const String& message, const v8::Handle<v8::Object>& creationContext, v8::Isolate* isolate) { return throwDOMException(ec, message, String(), creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.cpp deleted file mode 100644 index 6a70b502c32..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "bindings/v8/V8Utilities.h" - -#include "V8MessagePort.h" -#include "bindings/v8/ExceptionMessages.h" -#include "bindings/v8/ScriptState.h" -#include "bindings/v8/V8AbstractEventListener.h" -#include "bindings/v8/V8Binding.h" -#include "bindings/v8/custom/V8ArrayBufferCustom.h" -#include "core/dom/Document.h" -#include "core/dom/ExceptionCode.h" -#include "core/dom/ExecutionContext.h" -#include "core/dom/MessagePort.h" -#include "core/frame/Frame.h" -#include "core/workers/WorkerGlobalScope.h" -#include "wtf/ArrayBuffer.h" -#include "wtf/text/WTFString.h" -#include <v8.h> - - -namespace WebCore { - -// Use an array to hold dependents. It works like a ref-counted scheme. -// A value can be added more than once to the DOM object. -void createHiddenDependency(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex, v8::Isolate* isolate) -{ - v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); - if (cache->IsNull() || cache->IsUndefined()) { - cache = v8::Array::New(isolate); - object->SetInternalField(cacheIndex, cache); - } - - v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); - cacheArray->Set(v8::Integer::New(cacheArray->Length(), isolate), value); -} - -bool extractTransferables(v8::Local<v8::Value> value, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, bool& notASequence, v8::Isolate* isolate) -{ - if (isUndefinedOrNull(value)) { - ports.resize(0); - arrayBuffers.resize(0); - return true; - } - - uint32_t length = 0; - if (value->IsArray()) { - v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value); - length = array->Length(); - } else if (toV8Sequence(value, length, isolate).IsEmpty()) { - notASequence = true; - return false; - } - - v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value); - - // Validate the passed array of transferrables. - for (unsigned int i = 0; i < length; ++i) { - v8::Local<v8::Value> transferrable = transferrables->Get(i); - // Validation of non-null objects, per HTML5 spec 10.3.3. - if (isUndefinedOrNull(transferrable)) { - setDOMException(DataCloneError, isolate); - return false; - } - // Validation of Objects implementing an interface, per WebIDL spec 4.1.15. - if (V8MessagePort::hasInstance(transferrable, isolate, worldType(isolate))) { - RefPtr<MessagePort> port = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable)); - // Check for duplicate MessagePorts. - if (ports.contains(port)) { - setDOMException(DataCloneError, isolate); - return false; - } - ports.append(port.release()); - } else if (V8ArrayBuffer::hasInstance(transferrable, isolate, worldType(isolate))) - arrayBuffers.append(V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(transferrable))); - else { - setDOMException(DataCloneError, isolate); - return false; - } - } - return true; -} - -bool getMessagePortArray(v8::Local<v8::Value> value, const String& propertyName, MessagePortArray& ports, v8::Isolate* isolate) -{ - if (isUndefinedOrNull(value)) { - ports.resize(0); - return true; - } - if (!value->IsArray()) { - throwTypeError(ExceptionMessages::notASequenceTypeProperty(propertyName), isolate); - return false; - } - bool success = false; - ports = toRefPtrNativeArray<MessagePort, V8MessagePort>(value, propertyName, isolate, &success); - return success; -} - -bool getMessagePortArray(v8::Local<v8::Value> value, int argumentIndex, MessagePortArray& ports, v8::Isolate* isolate) -{ - if (isUndefinedOrNull(value)) { - ports.resize(0); - return true; - } - if (!value->IsArray()) { - throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); - return false; - } - bool success = false; - ports = toRefPtrNativeArray<MessagePort, V8MessagePort>(value, argumentIndex, isolate, &success); - return success; -} - -void removeHiddenDependency(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex, v8::Isolate* isolate) -{ - v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); - if (!cache->IsArray()) - return; - v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); - for (int i = cacheArray->Length() - 1; i >= 0; --i) { - v8::Local<v8::Value> cached = cacheArray->Get(v8::Integer::New(i, isolate)); - if (cached->StrictEquals(value)) { - cacheArray->Delete(i); - return; - } - } -} - -void transferHiddenDependency(v8::Handle<v8::Object> object, EventListener* oldValue, v8::Local<v8::Value> newValue, int cacheIndex, v8::Isolate* isolate) -{ - if (oldValue) { - V8AbstractEventListener* oldListener = V8AbstractEventListener::cast(oldValue); - if (oldListener) { - v8::Local<v8::Object> oldListenerObject = oldListener->getExistingListenerObject(); - if (!oldListenerObject.IsEmpty()) - removeHiddenDependency(object, oldListenerObject, cacheIndex, isolate); - } - } - // Non-callable input is treated as null and ignored - if (newValue->IsFunction()) - createHiddenDependency(object, newValue, cacheIndex, isolate); -} - -ExecutionContext* getExecutionContext() -{ - if (WorkerScriptController* controller = WorkerScriptController::controllerForContext()) - return &controller->workerGlobalScope(); - - return currentDocument(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.h b/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.h deleted file mode 100644 index 4a0efd41b96..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef V8Utilities_h -#define V8Utilities_h - -#include "wtf/Forward.h" -#include <v8.h> - -namespace WTF { -class ArrayBuffer; -} - -namespace WebCore { - - class EventListener; - class MessagePort; - class ExecutionContext; - - // Use an array to hold dependents. It works like a ref-counted scheme. A value can be added more than once to the DOM object. - void createHiddenDependency(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex, v8::Isolate*); - void removeHiddenDependency(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex, v8::Isolate*); - - // Combo create/remove, for EventHandler setters in generated bindings: - void transferHiddenDependency(v8::Handle<v8::Object>, EventListener* oldValue, v8::Local<v8::Value> newValue, int cacheIndex, v8::Isolate*); - - ExecutionContext* getExecutionContext(); - - typedef WTF::Vector<RefPtr<MessagePort>, 1> MessagePortArray; - typedef WTF::Vector<RefPtr<ArrayBuffer>, 1> ArrayBufferArray; - - // Helper function which pulls the values out of a JS sequence and into a MessagePortArray. - // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 - // of the HTML5 spec and generates exceptions as appropriate. If the supplied argument's type isn't - // a JS sequence, a type error is signalled by setting 'notASequence' to true -- the caller - // then being responsible for generating a TypeError having a message that fits the context. - // Returns true if the array was filled, or false if the passed value was not of an appropriate type. - bool extractTransferables(v8::Local<v8::Value>, MessagePortArray&, ArrayBufferArray&, bool& notASequence, v8::Isolate*); - - bool getMessagePortArray(v8::Local<v8::Value>, const String& propertyName, MessagePortArray&, v8::Isolate*); - bool getMessagePortArray(v8::Local<v8::Value>, int argumentIndex, MessagePortArray&, v8::Isolate*); - -} // namespace WebCore - -#endif // V8Utilities_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.cpp index 0681d0c059b..6d64a56169c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.cpp @@ -27,11 +27,33 @@ #include "bindings/v8/V8ValueCache.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "wtf/text/StringHash.h" namespace WebCore { +StringCacheMapTraits::MapType* StringCacheMapTraits::MapFromWeakCallbackData( + const v8::WeakCallbackData<v8::String, WeakCallbackDataType>& data) +{ + return &(V8PerIsolateData::from(data.GetIsolate())->stringCache()->m_stringCache); +} + + +void StringCacheMapTraits::Dispose( + v8::Isolate* isolate, v8::UniquePersistent<v8::String> value, StringImpl* key) +{ + V8PerIsolateData::from(isolate)->stringCache()->InvalidateLastString(); + key->deref(); +} + + +StringCache::~StringCache() +{ + // The MapType::Dispose callback calls StringCache::InvalidateLastString, + // which will only work while the destructor has not yet finished. Thus, + // we need to clear the map before the destructor has completed. + m_stringCache.Clear(); +} + static v8::Local<v8::String> makeExternalString(const String& string, v8::Isolate* isolate) { if (string.is8Bit()) { @@ -54,11 +76,11 @@ v8::Handle<v8::String> StringCache::v8ExternalStringSlow(StringImpl* stringImpl, if (!stringImpl->length()) return v8::String::Empty(isolate); - UnsafePersistent<v8::String> cachedV8String = m_stringCache.get(stringImpl); - if (!cachedV8String.isEmpty()) { + StringCacheMapTraits::MapType::PersistentValueReference cachedV8String = m_stringCache.GetReference(stringImpl); + if (!cachedV8String.IsEmpty()) { m_lastStringImpl = stringImpl; m_lastV8String = cachedV8String; - return cachedV8String.newLocal(isolate); + return m_lastV8String.NewLocal(isolate); } return createStringAndInsertIntoCache(stringImpl, isolate); @@ -71,11 +93,11 @@ void StringCache::setReturnValueFromStringSlow(v8::ReturnValue<v8::Value> return return; } - UnsafePersistent<v8::String> cachedV8String = m_stringCache.get(stringImpl); - if (!cachedV8String.isEmpty()) { + StringCacheMapTraits::MapType::PersistentValueReference cachedV8String = m_stringCache.GetReference(stringImpl); + if (!cachedV8String.IsEmpty()) { m_lastStringImpl = stringImpl; m_lastV8String = cachedV8String; - returnValue.Set(*cachedV8String.persistent()); + m_lastV8String.SetReturnValue(returnValue); return; } @@ -84,34 +106,27 @@ void StringCache::setReturnValueFromStringSlow(v8::ReturnValue<v8::Value> return v8::Local<v8::String> StringCache::createStringAndInsertIntoCache(StringImpl* stringImpl, v8::Isolate* isolate) { - ASSERT(!m_stringCache.contains(stringImpl)); + ASSERT(!m_stringCache.Contains(stringImpl)); ASSERT(stringImpl->length()); v8::Local<v8::String> newString = makeExternalString(String(stringImpl), isolate); if (newString.IsEmpty()) return newString; - v8::Persistent<v8::String> wrapper(isolate, newString); + v8::UniquePersistent<v8::String> wrapper(isolate, newString); stringImpl->ref(); wrapper.MarkIndependent(); - wrapper.SetWeak(stringImpl, &setWeakCallback); - m_lastV8String = UnsafePersistent<v8::String>(wrapper); + m_stringCache.Set(stringImpl, wrapper.Pass(), &m_lastV8String); m_lastStringImpl = stringImpl; - m_stringCache.set(stringImpl, m_lastV8String); return newString; } -void StringCache::setWeakCallback(const v8::WeakCallbackData<v8::String, StringImpl>& data) +void StringCache::InvalidateLastString() { - StringCache* stringCache = V8PerIsolateData::from(data.GetIsolate())->stringCache(); - stringCache->m_lastStringImpl = 0; - stringCache->m_lastV8String.clear(); - ASSERT(stringCache->m_stringCache.contains(data.GetParameter())); - stringCache->m_stringCache.get(data.GetParameter()).dispose(); - stringCache->m_stringCache.remove(data.GetParameter()); - data.GetParameter()->deref(); + m_lastStringImpl = nullptr; + m_lastV8String.Reset(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.h b/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.h index 44ee8db6e80..8110cd38d27 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.h @@ -26,7 +26,7 @@ #ifndef V8ValueCache_h #define V8ValueCache_h -#include "bindings/v8/UnsafePersistent.h" +#include "bindings/v8/V8PersistentValueMap.h" #include <v8.h> #include "wtf/HashMap.h" #include "wtf/RefPtr.h" @@ -35,15 +35,39 @@ namespace WebCore { +class StringCacheMapTraits : public V8PersistentValueMapTraits<StringImpl*, v8::String, true> { +public: + // Weak traits: + typedef StringImpl WeakCallbackDataType; + typedef v8::PersistentValueMap<StringImpl*, v8::String, StringCacheMapTraits> MapType; + + static WeakCallbackDataType* WeakCallbackParameter( + MapType* map, StringImpl* key, v8::Local<v8::String>& value) { return key; } + static void DisposeCallbackData(WeakCallbackDataType* callbackData) { } + + static MapType* MapFromWeakCallbackData( + const v8::WeakCallbackData<v8::String, WeakCallbackDataType>&); + + static StringImpl* KeyFromWeakCallbackData( + const v8::WeakCallbackData<v8::String, WeakCallbackDataType>& data) + { + return data.GetParameter(); + } + + static void Dispose(v8::Isolate*, v8::UniquePersistent<v8::String> value, StringImpl* key); +}; + + class StringCache { public: - StringCache() { } + StringCache(v8::Isolate* isolate) : m_stringCache(isolate) { } + ~StringCache(); v8::Handle<v8::String> v8ExternalString(StringImpl* stringImpl, v8::Isolate* isolate) { ASSERT(stringImpl); if (m_lastStringImpl.get() == stringImpl) - return m_lastV8String.newLocal(isolate); + return m_lastV8String.NewLocal(isolate); return v8ExternalStringSlow(stringImpl, isolate); } @@ -51,20 +75,22 @@ public: { ASSERT(stringImpl); if (m_lastStringImpl.get() == stringImpl) - returnValue.Set(*m_lastV8String.persistent()); + m_lastV8String.SetReturnValue(returnValue); else setReturnValueFromStringSlow(returnValue, stringImpl); } -private: - static void setWeakCallback(const v8::WeakCallbackData<v8::String, StringImpl>&); + friend class StringCacheMapTraits; +private: v8::Handle<v8::String> v8ExternalStringSlow(StringImpl*, v8::Isolate*); void setReturnValueFromStringSlow(v8::ReturnValue<v8::Value>, StringImpl*); v8::Local<v8::String> createStringAndInsertIntoCache(StringImpl*, v8::Isolate*); + void InvalidateLastString(); + + StringCacheMapTraits::MapType m_stringCache; + StringCacheMapTraits::MapType::PersistentValueReference m_lastV8String; - HashMap<StringImpl*, UnsafePersistent<v8::String> > m_stringCache; - UnsafePersistent<v8::String> m_lastV8String; // Note: RefPtr is a must as we cache by StringImpl* equality, not identity // hence lastStringImpl might be not a key of the cache (in sense of identity) // and hence it's not refed on addition. diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.cpp index 3474312da86..8b9e8b2dbfb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.cpp @@ -31,28 +31,30 @@ #include "config.h" #include "bindings/v8/V8WindowShell.h" -#include "RuntimeEnabledFeatures.h" -#include "V8Document.h" -#include "V8HTMLCollection.h" -#include "V8HTMLDocument.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8HTMLCollection.h" +#include "bindings/core/v8/V8HTMLDocument.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8DOMActivityLogger.h" #include "bindings/v8/V8GCForContextDispose.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8Initializer.h" #include "bindings/v8/V8ObjectConstructor.h" -#include "bindings/v8/V8PerContextData.h" +#include "core/dom/ScriptForbiddenScope.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/html/HTMLCollection.h" #include "core/html/HTMLIFrameElement.h" #include "core/inspector/InspectorInstrumentation.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/Frame.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/TraceEvent.h" +#include "platform/heap/Handle.h" #include "platform/weborigin/SecurityOrigin.h" #include "public/platform/Platform.h" #include "wtf/Assertions.h" @@ -77,33 +79,31 @@ static void setInjectedScriptContextDebugId(v8::Handle<v8::Context> targetContex V8PerContextDebugData::setContextDebugData(targetContext, "injected", debugId); } -PassOwnPtr<V8WindowShell> V8WindowShell::create(Frame* frame, PassRefPtr<DOMWrapperWorld> world, v8::Isolate* isolate) +PassOwnPtr<V8WindowShell> V8WindowShell::create(LocalFrame* frame, DOMWrapperWorld& world, v8::Isolate* isolate) { - return adoptPtr(new V8WindowShell(frame, world, isolate)); + return adoptPtr(new V8WindowShell(frame, &world, isolate)); } -V8WindowShell::V8WindowShell(Frame* frame, PassRefPtr<DOMWrapperWorld> world, v8::Isolate* isolate) +V8WindowShell::V8WindowShell(LocalFrame* frame, PassRefPtr<DOMWrapperWorld> world, v8::Isolate* isolate) : m_frame(frame) - , m_world(world) , m_isolate(isolate) + , m_world(world) { } void V8WindowShell::disposeContext(GlobalDetachmentBehavior behavior) { - m_perContextData.clear(); - - if (!m_contextHolder) + if (!isContextInitialized()) return; v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> context = m_contextHolder->context(); + v8::Handle<v8::Context> context = m_scriptState->context(); m_frame->loader().client()->willReleaseScriptContext(context, m_world->worldId()); if (behavior == DetachGlobal) context->DetachGlobal(); - m_contextHolder.clear(); + m_scriptState->disposePerContextData(); // It's likely that disposing the context has created a lot of // garbage. Notify V8 about this so it'll have a chance of cleaning @@ -111,12 +111,9 @@ void V8WindowShell::disposeContext(GlobalDetachmentBehavior behavior) V8GCForContextDispose::instanceTemplate().notifyContextDisposed(m_frame->isMainFrame()); } -void V8WindowShell::clearForClose(bool destroyGlobal) +void V8WindowShell::clearForClose() { - if (destroyGlobal) - m_global.clear(); - - if (!m_contextHolder) + if (!isContextInitialized()) return; m_document.clear(); @@ -125,21 +122,19 @@ void V8WindowShell::clearForClose(bool destroyGlobal) void V8WindowShell::clearForNavigation() { - if (!m_contextHolder) + if (!isContextInitialized()) return; - v8::HandleScope handleScope(m_isolate); - m_document.clear(); + ScriptState::Scope scope(m_scriptState.get()); - v8::Handle<v8::Context> context = m_contextHolder->context(); - v8::Context::Scope contextScope(context); + m_document.clear(); // Clear the document wrapper cache before turning on access checks on - // the old DOMWindow wrapper. This way, access to the document wrapper - // will be protected by the security checks on the DOMWindow wrapper. + // the old LocalDOMWindow wrapper. This way, access to the document wrapper + // will be protected by the security checks on the LocalDOMWindow wrapper. clearDocumentProperty(); - v8::Handle<v8::Object> windowWrapper = m_global.newLocal(m_isolate)->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate))); + v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(m_global.newLocal(m_isolate), m_isolate); ASSERT(!windowWrapper.IsEmpty()); windowWrapper->TurnOnAccessCheck(); disposeContext(DetachGlobal); @@ -147,16 +142,16 @@ void V8WindowShell::clearForNavigation() // Create a new environment and setup the global object. // -// The global object corresponds to a DOMWindow instance. However, to -// allow properties of the JS DOMWindow instance to be shadowed, we -// use a shadow object as the global object and use the JS DOMWindow -// instance as the prototype for that shadow object. The JS DOMWindow +// The global object corresponds to a LocalDOMWindow instance. However, to +// allow properties of the JS LocalDOMWindow instance to be shadowed, we +// use a shadow object as the global object and use the JS LocalDOMWindow +// instance as the prototype for that shadow object. The JS LocalDOMWindow // instance is undetectable from JavaScript code because the __proto__ // accessors skip that object. // -// The shadow object and the DOMWindow instance are seen as one object +// The shadow object and the LocalDOMWindow instance are seen as one object // from JavaScript. The JavaScript object that corresponds to a -// DOMWindow instance is the shadow object. When mapping a DOMWindow +// LocalDOMWindow instance is the shadow object. When mapping a LocalDOMWindow // instance to a V8 object, we return the shadow object. // // To implement split-window, see @@ -169,7 +164,7 @@ void V8WindowShell::clearForNavigation() // global object of the context. A variable declared in the global // scope is a property of the inner window. // -// The outer window sticks to a Frame, it is exposed to JavaScript +// The outer window sticks to a LocalFrame, it is exposed to JavaScript // via window.window, window.self, window.parent, etc. The outer window // has a security token which is the domain. The outer window cannot // have its own properties. window.foo = 'x' is delegated to the @@ -182,27 +177,31 @@ void V8WindowShell::clearForNavigation() // it won't be able to reach the outer window via its global object. bool V8WindowShell::initializeIfNeeded() { - if (m_contextHolder) + if (isContextInitialized()) return true; - TRACE_EVENT0("v8", "V8WindowShell::initializeIfNeeded"); - - v8::HandleScope handleScope(m_isolate); - - createContext(); - if (!m_contextHolder) - return false; + DOMWrapperWorld::setWorldOfInitializingWindow(m_world.get()); + bool result = initialize(); + DOMWrapperWorld::setWorldOfInitializingWindow(0); + return result; +} - v8::Handle<v8::Context> context = m_contextHolder->context(); +bool V8WindowShell::initialize() +{ + TRACE_EVENT0("v8", "V8WindowShell::initialize"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "InitializeWindow"); - V8PerContextDataHolder::install(context); + ScriptForbiddenScope::AllowUserAgentScript allowScript; - m_world->setIsolatedWorldField(context); + v8::HandleScope handleScope(m_isolate); - bool isMainWorld = m_world->isMainWorld(); + createContext(); - v8::Context::Scope contextScope(context); + if (!isContextInitialized()) + return false; + ScriptState::Scope scope(m_scriptState.get()); + v8::Handle<v8::Context> context = m_scriptState->context(); if (m_global.isEmpty()) { m_global.set(m_isolate, context->Global()); if (m_global.isEmpty()) { @@ -211,44 +210,32 @@ bool V8WindowShell::initializeIfNeeded() } } - if (!isMainWorld) { - V8WindowShell* mainWindow = m_frame->script().existingWindowShell(mainThreadNormalWorld()); + if (!m_world->isMainWorld()) { + V8WindowShell* mainWindow = m_frame->script().existingWindowShell(DOMWrapperWorld::mainWorld()); if (mainWindow && !mainWindow->context().IsEmpty()) setInjectedScriptContextDebugId(context, m_frame->script().contextDebugId(mainWindow->context())); } - m_perContextData = V8PerContextData::create(context); - if (!m_perContextData->init()) { - disposeContext(DoNotDetachGlobal); - return false; - } - m_perContextData->setActivityLogger(DOMWrapperWorld::activityLogger(m_world->worldId())); if (!installDOMWindow()) { disposeContext(DoNotDetachGlobal); return false; } - if (isMainWorld) { + if (m_world->isMainWorld()) { + // ActivityLogger for main world is updated within updateDocument(). updateDocument(); - setSecurityToken(); if (m_frame->document()) { + setSecurityToken(m_frame->document()->securityOrigin()); ContentSecurityPolicy* csp = m_frame->document()->contentSecurityPolicy(); context->AllowCodeGenerationFromStrings(csp->allowEval(0, ContentSecurityPolicy::SuppressReport)); context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, csp->evalDisabledErrorMessage())); } } else { - // Using the default security token means that the canAccess is always - // called, which is slow. - // FIXME: Use tokens where possible. This will mean keeping track of all - // created contexts so that they can all be updated when the - // document domain - // changes. - context->UseDefaultSecurityToken(); - + updateActivityLogger(); SecurityOrigin* origin = m_world->isolatedWorldSecurityOrigin(); + setSecurityToken(origin); if (origin && InspectorInstrumentation::hasFrontends()) { - ScriptState* scriptState = ScriptState::forContext(v8::Local<v8::Context>::New(m_isolate, context)); - InspectorInstrumentation::didCreateIsolatedContext(m_frame, scriptState, origin); + InspectorInstrumentation::didCreateIsolatedContext(m_frame, m_scriptState.get(), origin); } } m_frame->loader().client()->didCreateScriptContext(context, m_world->extensionGroup(), m_world->worldId()); @@ -257,14 +244,14 @@ bool V8WindowShell::initializeIfNeeded() void V8WindowShell::createContext() { - // The activeDocumentLoader pointer could be 0 during frame shutdown. + // The documentLoader pointer could be 0 during frame shutdown. // FIXME: Can we remove this check? - if (!m_frame->loader().activeDocumentLoader()) + if (!m_frame->loader().documentLoader()) return; // Create a new environment using an empty template for the shadow // object. Reuse the global object if one has been created earlier. - v8::Handle<v8::ObjectTemplate> globalTemplate = V8Window::GetShadowObjectTemplate(m_isolate, m_world->isMainWorld() ? MainWorld : IsolatedWorld); + v8::Handle<v8::ObjectTemplate> globalTemplate = V8Window::getShadowObjectTemplate(m_isolate); if (globalTemplate.IsEmpty()) return; @@ -284,12 +271,10 @@ void V8WindowShell::createContext() } v8::ExtensionConfiguration extensionConfiguration(index, extensionNames.get()); - v8::HandleScope handleScope(m_isolate); v8::Handle<v8::Context> context = v8::Context::New(m_isolate, &extensionConfiguration, globalTemplate, m_global.newLocal(m_isolate)); - if (!context.IsEmpty()) { - m_contextHolder = adoptPtr(new gin::ContextHolder(m_isolate)); - m_contextHolder->SetContext(context); - } + if (context.IsEmpty()) + return; + m_scriptState = ScriptState::create(context, m_world); double contextCreationDurationInMilliseconds = (currentTime() - contextCreationStartInSeconds) * 1000; const char* histogramName = "WebCore.V8WindowShell.createContext.MainWorld"; @@ -298,36 +283,46 @@ void V8WindowShell::createContext() blink::Platform::current()->histogramCustomCounts(histogramName, contextCreationDurationInMilliseconds, 0, 10000, 50); } +static v8::Handle<v8::Object> toInnerGlobalObject(v8::Handle<v8::Context> context) +{ + return v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); +} + bool V8WindowShell::installDOMWindow() { - DOMWrapperWorld::setInitializingWindow(true); - DOMWindow* window = m_frame->domWindow(); - v8::Local<v8::Object> windowWrapper = V8ObjectConstructor::newInstance(V8PerContextData::from(m_contextHolder->context())->constructorForType(&V8Window::wrapperTypeInfo)); + LocalDOMWindow* window = m_frame->domWindow(); + v8::Local<v8::Object> windowWrapper = V8ObjectConstructor::newInstance(m_isolate, m_scriptState->perContextData()->constructorForType(&V8Window::wrapperTypeInfo)); if (windowWrapper.IsEmpty()) return false; V8Window::installPerContextEnabledProperties(windowWrapper, window, m_isolate); - V8DOMWrapper::setNativeInfo(v8::Handle<v8::Object>::Cast(windowWrapper->GetPrototype()), &V8Window::wrapperTypeInfo, window); + V8DOMWrapper::setNativeInfoForHiddenWrapper(v8::Handle<v8::Object>::Cast(windowWrapper->GetPrototype()), &V8Window::wrapperTypeInfo, window); // Install the windowWrapper as the prototype of the innerGlobalObject. // The full structure of the global object is as follows: // // outerGlobalObject (Empty object, remains after navigation) // -- has prototype --> innerGlobalObject (Holds global variables, changes during navigation) - // -- has prototype --> DOMWindow instance + // -- has prototype --> LocalDOMWindow instance // -- has prototype --> Window.prototype // -- has prototype --> Object.prototype // // Note: Much of this prototype structure is hidden from web content. The - // outer, inner, and DOMWindow instance all appear to be the same + // outer, inner, and LocalDOMWindow instance all appear to be the same // JavaScript object. // - v8::Handle<v8::Object> innerGlobalObject = toInnerGlobalObject(m_contextHolder->context()); - V8DOMWrapper::setNativeInfo(innerGlobalObject, &V8Window::wrapperTypeInfo, window); + // Note: With Oilpan, the LocalDOMWindow object is garbage collected. + // Persistent references to this inner global object view of the LocalDOMWindow + // aren't kept, as that would prevent the global object from ever being released. + // It is safe not to do so, as the wrapper for the LocalDOMWindow being installed here + // already keeps a persistent reference, and it along with the inner global object + // views of the LocalDOMWindow will die together once that wrapper clears the persistent + // reference. + v8::Handle<v8::Object> innerGlobalObject = toInnerGlobalObject(m_scriptState->context()); + V8DOMWrapper::setNativeInfoForHiddenWrapper(innerGlobalObject, &V8Window::wrapperTypeInfo, window); innerGlobalObject->SetPrototype(windowWrapper); - V8DOMWrapper::associateObjectWithWrapper<V8Window>(PassRefPtr<DOMWindow>(window), &V8Window::wrapperTypeInfo, windowWrapper, m_isolate, WrapperConfiguration::Dependent); - DOMWrapperWorld::setInitializingWindow(false); + V8DOMWrapper::associateObjectWithWrapper<V8Window>(PassRefPtrWillBeRawPtr<LocalDOMWindow>(window), &V8Window::wrapperTypeInfo, windowWrapper, m_isolate, WrapperConfiguration::Dependent); return true; } @@ -342,18 +337,16 @@ void V8WindowShell::updateDocumentProperty() if (!m_world->isMainWorld()) return; - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> context = m_contextHolder->context(); - v8::Context::Scope contextScope(context); - - v8::Handle<v8::Value> documentWrapper = toV8(m_frame->document(), v8::Handle<v8::Object>(), context->GetIsolate()); + ScriptState::Scope scope(m_scriptState.get()); + v8::Handle<v8::Context> context = m_scriptState->context(); + v8::Handle<v8::Value> documentWrapper = toV8(m_frame->document(), context->Global(), context->GetIsolate()); ASSERT(documentWrapper == m_document.newLocal(m_isolate) || m_document.isEmpty()); if (m_document.isEmpty()) updateDocumentWrapper(v8::Handle<v8::Object>::Cast(documentWrapper)); checkDocumentWrapper(m_document.newLocal(m_isolate), m_frame->document()); // If instantiation of the document wrapper fails, clear the cache - // and let the DOMWindow accessor handle access to the document. + // and let the LocalDOMWindow accessor handle access to the document. if (documentWrapper.IsEmpty()) { clearDocumentProperty(); return; @@ -362,38 +355,40 @@ void V8WindowShell::updateDocumentProperty() context->Global()->ForceSet(v8AtomicString(m_isolate, "document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); // We also stash a reference to the document on the inner global object so that - // DOMWindow objects we obtain from JavaScript references are guaranteed to have + // LocalDOMWindow objects we obtain from JavaScript references are guaranteed to have // live Document objects. - toInnerGlobalObject(context)->SetHiddenValue(V8HiddenPropertyName::document(m_isolate), documentWrapper); + V8HiddenValue::setHiddenValue(m_isolate, toInnerGlobalObject(context), V8HiddenValue::document(m_isolate), documentWrapper); } void V8WindowShell::clearDocumentProperty() { - ASSERT(m_contextHolder); + ASSERT(isContextInitialized()); if (!m_world->isMainWorld()) return; v8::HandleScope handleScope(m_isolate); - m_contextHolder->context()->Global()->ForceDelete(v8AtomicString(m_isolate, "document")); + m_scriptState->context()->Global()->ForceDelete(v8AtomicString(m_isolate, "document")); } -void V8WindowShell::setSecurityToken() +void V8WindowShell::updateActivityLogger() { - ASSERT(m_world->isMainWorld()); - - Document* document = m_frame->document(); + m_scriptState->perContextData()->setActivityLogger(V8DOMActivityLogger::activityLogger( + m_world->worldId(), m_frame->document() ? m_frame->document()->baseURI() : KURL())); +} - // Ask the document's SecurityOrigin to generate a security token. +void V8WindowShell::setSecurityToken(SecurityOrigin* origin) +{ // If two tokens are equal, then the SecurityOrigins canAccess each other. // If two tokens are not equal, then we have to call canAccess. // Note: we can't use the HTTPOrigin if it was set from the DOM. - SecurityOrigin* origin = document->securityOrigin(); String token; // We stick with an empty token if document.domain was modified or if we // are in the initial empty document, so that we can do a full canAccess // check in those cases. - if (!origin->domainWasSetInDOM() - && !m_frame->loader().stateMachine()->isDisplayingInitialEmptyDocument()) - token = document->securityOrigin()->toString(); + bool delaySet = m_world->isMainWorld() + && (origin->domainWasSetInDOM() + || m_frame->loader().stateMachine()->isDisplayingInitialEmptyDocument()); + if (origin && !delaySet) + token = origin->toString(); // An empty or "null" token means we always have to call // canAccess. The toString method on securityOrigins returns the @@ -402,7 +397,7 @@ void V8WindowShell::setSecurityToken() // case, we use the global object as the security token to avoid // calling canAccess when a script accesses its own objects. v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> context = m_contextHolder->context(); + v8::Handle<v8::Context> context = m_scriptState->context(); if (token.isEmpty() || token == "null") { context->UseDefaultSecurityToken(); return; @@ -417,12 +412,13 @@ void V8WindowShell::setSecurityToken() void V8WindowShell::updateDocument() { ASSERT(m_world->isMainWorld()); - if (m_global.isEmpty()) + if (!isGlobalInitialized()) return; - if (!m_contextHolder) + if (!isContextInitialized()) return; + updateActivityLogger(); updateDocumentProperty(); - updateSecurityOrigin(); + updateSecurityOrigin(m_frame->document()->securityOrigin()); } static v8::Handle<v8::Value> getNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) @@ -430,16 +426,17 @@ static v8::Handle<v8::Value> getNamedProperty(HTMLDocument* htmlDocument, const if (!htmlDocument->hasNamedItem(key) && !htmlDocument->hasExtraNamedItem(key)) return v8Undefined(); - RefPtr<HTMLCollection> items = htmlDocument->documentNamedItems(key); + RefPtrWillBeRawPtr<HTMLCollection> items = htmlDocument->documentNamedItems(key); if (items->isEmpty()) return v8Undefined(); if (items->hasExactlyOneItem()) { - Node* node = items->item(0); + Element* element = items->item(0); + ASSERT(element); Frame* frame = 0; - if (node->hasTagName(HTMLNames::iframeTag) && (frame = toHTMLIFrameElement(node)->contentFrame())) + if (isHTMLIFrameElement(*element) && (frame = toHTMLIFrameElement(*element).contentFrame())) return toV8(frame->domWindow(), creationContext, isolate); - return toV8(node, creationContext, isolate); + return toV8(element, creationContext, isolate); } return toV8(items.release(), creationContext, isolate); } @@ -466,12 +463,10 @@ void V8WindowShell::namedItemAdded(HTMLDocument* document, const AtomicString& n { ASSERT(m_world->isMainWorld()); - if (!m_contextHolder) + if (!isContextInitialized()) return; - v8::HandleScope handleScope(m_isolate); - v8::Context::Scope contextScope(m_contextHolder->context()); - + ScriptState::Scope scope(m_scriptState.get()); ASSERT(!m_document.isEmpty()); v8::Handle<v8::Object> documentHandle = m_document.newLocal(m_isolate); checkDocumentWrapper(documentHandle, document); @@ -482,28 +477,25 @@ void V8WindowShell::namedItemRemoved(HTMLDocument* document, const AtomicString& { ASSERT(m_world->isMainWorld()); - if (!m_contextHolder) + if (!isContextInitialized()) return; if (document->hasNamedItem(name) || document->hasExtraNamedItem(name)) return; - v8::HandleScope handleScope(m_isolate); - v8::Context::Scope contextScope(m_contextHolder->context()); - + ScriptState::Scope scope(m_scriptState.get()); ASSERT(!m_document.isEmpty()); v8::Handle<v8::Object> documentHandle = m_document.newLocal(m_isolate); checkDocumentWrapper(documentHandle, document); documentHandle->Delete(v8String(m_isolate, name)); } -void V8WindowShell::updateSecurityOrigin() +void V8WindowShell::updateSecurityOrigin(SecurityOrigin* origin) { ASSERT(m_world->isMainWorld()); - if (!m_contextHolder) + if (!isContextInitialized()) return; - v8::HandleScope handleScope(m_isolate); - setSecurityToken(); + setSecurityToken(origin); } } // WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.h b/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.h index b1c65ab9f42..548caa388fe 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.h @@ -33,9 +33,8 @@ #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/V8PerContextData.h" +#include "bindings/v8/ScriptState.h" #include "bindings/v8/WrapperTypeInfo.h" -#include "gin/public/context_holder.h" #include "platform/weborigin/SecurityOrigin.h" #include "wtf/Forward.h" #include "wtf/HashMap.h" @@ -47,17 +46,19 @@ namespace WebCore { -class DOMWindow; -class Frame; +class LocalDOMWindow; +class LocalFrame; class HTMLDocument; +class SecurityOrigin; -// V8WindowShell represents all the per-global object state for a Frame that +// V8WindowShell represents all the per-global object state for a LocalFrame that // persist between navigations. class V8WindowShell { public: - static PassOwnPtr<V8WindowShell> create(Frame*, PassRefPtr<DOMWrapperWorld>, v8::Isolate*); + static PassOwnPtr<V8WindowShell> create(LocalFrame*, DOMWrapperWorld&, v8::Isolate*); - v8::Local<v8::Context> context() const { return m_contextHolder ? m_contextHolder->context() : v8::Local<v8::Context>(); } + v8::Local<v8::Context> context() const { return m_scriptState ? m_scriptState->context() : v8::Local<v8::Context>(); } + ScriptState* scriptState() const { return m_scriptState.get(); } // Update document object of the frame. void updateDocument(); @@ -67,21 +68,22 @@ public: // Update the security origin of a document // (e.g., after setting docoument.domain). - void updateSecurityOrigin(); + void updateSecurityOrigin(SecurityOrigin*); - bool isContextInitialized() { return m_contextHolder; } + bool isContextInitialized() { return m_scriptState && !!m_scriptState->perContextData(); } bool isGlobalInitialized() { return !m_global.isEmpty(); } bool initializeIfNeeded(); void updateDocumentWrapper(v8::Handle<v8::Object> wrapper); void clearForNavigation(); - void clearForClose(bool destroyGlobal); + void clearForClose(); - DOMWrapperWorld* world() { return m_world.get(); } + DOMWrapperWorld& world() { return *m_world; } private: - V8WindowShell(Frame*, PassRefPtr<DOMWrapperWorld>, v8::Isolate*); + V8WindowShell(LocalFrame*, PassRefPtr<DOMWrapperWorld>, v8::Isolate*); + bool initialize(); enum GlobalDetachmentBehavior { DoNotDetachGlobal, @@ -89,7 +91,7 @@ private: }; void disposeContext(GlobalDetachmentBehavior); - void setSecurityToken(); + void setSecurityToken(SecurityOrigin*); // The JavaScript wrapper for the document object is cached on the global // object for fast access. UpdateDocumentProperty sets the wrapper @@ -98,18 +100,18 @@ private: void updateDocumentProperty(); void clearDocumentProperty(); + // Updates Activity Logger for the current context. + void updateActivityLogger(); + void createContext(); bool installDOMWindow(); static V8WindowShell* enteredIsolatedWorldContext(); - Frame* m_frame; - RefPtr<DOMWrapperWorld> m_world; + LocalFrame* m_frame; v8::Isolate* m_isolate; - - OwnPtr<V8PerContextData> m_perContextData; - - OwnPtr<gin::ContextHolder> m_contextHolder; + RefPtr<ScriptState> m_scriptState; + RefPtr<DOMWrapperWorld> m_world; ScopedPersistent<v8::Object> m_global; ScopedPersistent<v8::Object> m_document; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.cpp index da79d52d1c8..c66b8a24dc9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.cpp @@ -32,94 +32,84 @@ #include "bindings/v8/V8WorkerGlobalScopeEventListener.h" -#include "V8Event.h" -#include "V8EventTarget.h" +#include "bindings/core/v8/V8Event.h" +#include "bindings/core/v8/V8EventTarget.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" #include "bindings/v8/V8GCController.h" #include "bindings/v8/V8ScriptRunner.h" #include "bindings/v8/WorkerScriptController.h" #include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/workers/WorkerGlobalScope.h" namespace WebCore { -V8WorkerGlobalScopeEventListener::V8WorkerGlobalScopeEventListener(v8::Local<v8::Object> listener, bool isInline, v8::Isolate* isolate) - : V8EventListener(listener, isInline, isolate) +V8WorkerGlobalScopeEventListener::V8WorkerGlobalScopeEventListener(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) + : V8EventListener(listener, isInline, scriptState) { } -void V8WorkerGlobalScopeEventListener::handleEvent(ExecutionContext* context, Event* event) +void V8WorkerGlobalScopeEventListener::handleEvent(ExecutionContext*, Event* event) { - if (!context) - return; - // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it. // See issue 889829. RefPtr<V8AbstractEventListener> protect(this); - v8::Isolate* isolate = toIsolate(context); - v8::HandleScope handleScope(isolate); - - WorkerScriptController* script = toWorkerGlobalScope(context)->script(); + WorkerScriptController* script = toWorkerGlobalScope(scriptState()->executionContext())->script(); if (!script) return; - v8::Handle<v8::Context> v8Context = script->context(); - if (v8Context.IsEmpty()) + if (scriptState()->contextIsEmpty()) return; - - // Enter the V8 context in which to perform the event handling. - v8::Context::Scope scope(v8Context); + ScriptState::Scope scope(scriptState()); // Get the V8 wrapper for the event object. - v8::Handle<v8::Value> jsEvent = toV8(event, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> jsEvent = toV8(event, scriptState()->context()->Global(), isolate()); - invokeEventHandler(context, event, v8::Local<v8::Value>::New(isolate, jsEvent)); + invokeEventHandler(event, v8::Local<v8::Value>::New(isolate(), jsEvent)); } -v8::Local<v8::Value> V8WorkerGlobalScopeEventListener::callListenerFunction(ExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) +v8::Local<v8::Value> V8WorkerGlobalScopeEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { - v8::Local<v8::Function> handlerFunction = getListenerFunction(context); - v8::Local<v8::Object> receiver = getReceiverObject(context, event); + v8::Local<v8::Function> handlerFunction = getListenerFunction(scriptState()->executionContext()); + v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "FunctionCall", "data", devToolsTraceEventData(scriptState()->executionContext(), handlerFunction, isolate())); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie; - if (InspectorInstrumentation::timelineAgentEnabled(context)) { - String resourceName("undefined"); + if (InspectorInstrumentation::timelineAgentEnabled(scriptState()->executionContext())) { + int scriptId = 0; + String resourceName; int lineNumber = 1; - v8::ScriptOrigin origin = handlerFunction->GetScriptOrigin(); - if (!origin.ResourceName().IsEmpty()) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringResourceName, origin.ResourceName(), v8::Local<v8::Value>()); - resourceName = stringResourceName; - lineNumber = handlerFunction->GetScriptLineNumber() + 1; - } - cookie = InspectorInstrumentation::willCallFunction(context, resourceName, lineNumber); + GetDevToolsFunctionInfo(handlerFunction, isolate(), scriptId, resourceName, lineNumber); + cookie = InspectorInstrumentation::willCallFunction(scriptState()->executionContext(), scriptId, resourceName, lineNumber); } - v8::Isolate* isolate = toIsolate(context); v8::Handle<v8::Value> parameters[1] = { jsEvent }; - v8::Local<v8::Value> result = V8ScriptRunner::callFunction(handlerFunction, context, receiver, WTF_ARRAY_LENGTH(parameters), parameters, isolate); + v8::Local<v8::Value> result = V8ScriptRunner::callFunction(handlerFunction, scriptState()->executionContext(), receiver, WTF_ARRAY_LENGTH(parameters), parameters, isolate()); InspectorInstrumentation::didCallFunction(cookie); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); return result; } -v8::Local<v8::Object> V8WorkerGlobalScopeEventListener::getReceiverObject(ExecutionContext* context, Event* event) +v8::Local<v8::Object> V8WorkerGlobalScopeEventListener::getReceiverObject(Event* event) { - v8::Local<v8::Object> listener = getListenerObject(context); + v8::Local<v8::Object> listener = getListenerObject(scriptState()->executionContext()); if (!listener.IsEmpty() && !listener->IsFunction()) return listener; EventTarget* target = event->currentTarget(); - v8::Isolate* isolate = toIsolate(context); - v8::Handle<v8::Value> value = toV8(target, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> value = toV8(target, scriptState()->context()->Global(), isolate()); if (value.IsEmpty()) return v8::Local<v8::Object>(); - return v8::Local<v8::Object>::New(isolate, v8::Handle<v8::Object>::Cast(value)); + return v8::Local<v8::Object>::New(isolate(), v8::Handle<v8::Object>::Cast(value)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.h b/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.h index 1acf7c44d7d..355a424afbc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.h @@ -39,21 +39,21 @@ namespace WebCore { class Event; - class V8WorkerGlobalScopeEventListener : public V8EventListener { + class V8WorkerGlobalScopeEventListener FINAL : public V8EventListener { public: - static PassRefPtr<V8WorkerGlobalScopeEventListener> create(v8::Local<v8::Object> listener, bool isInline, v8::Isolate* isolate) + static PassRefPtr<V8WorkerGlobalScopeEventListener> create(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) { - return adoptRef(new V8WorkerGlobalScopeEventListener(listener, isInline, isolate)); + return adoptRef(new V8WorkerGlobalScopeEventListener(listener, isInline, scriptState)); } - virtual void handleEvent(ExecutionContext*, Event*); + virtual void handleEvent(ExecutionContext*, Event*) OVERRIDE; protected: - V8WorkerGlobalScopeEventListener(v8::Local<v8::Object> listener, bool isInline, v8::Isolate*); + V8WorkerGlobalScopeEventListener(v8::Local<v8::Object> listener, bool isInline, ScriptState*); private: - virtual v8::Local<v8::Value> callListenerFunction(ExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); - v8::Local<v8::Object> getReceiverObject(ExecutionContext*, Event*); + virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*) OVERRIDE; + v8::Local<v8::Object> getReceiverObject(Event*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.cpp b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.cpp index 27170fecf89..3381f46b221 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.cpp @@ -32,10 +32,10 @@ #include "bindings/v8/WorkerScriptController.h" -#include "V8DedicatedWorkerGlobalScope.h" -#include "V8ServiceWorkerGlobalScope.h" -#include "V8SharedWorkerGlobalScope.h" -#include "V8WorkerGlobalScope.h" +#include "bindings/core/v8/V8DedicatedWorkerGlobalScope.h" +#include "bindings/core/v8/V8SharedWorkerGlobalScope.h" +#include "bindings/core/v8/V8WorkerGlobalScope.h" +#include "bindings/modules/v8/V8ServiceWorkerGlobalScope.h" #include "bindings/v8/ScriptSourceCode.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8ErrorHandler.h" @@ -50,6 +50,7 @@ #include "core/workers/WorkerGlobalScope.h" #include "core/workers/WorkerObjectProxy.h" #include "core/workers/WorkerThread.h" +#include "platform/heap/ThreadState.h" #include <v8.h> #include "public/platform/Platform.h" @@ -58,67 +59,77 @@ namespace WebCore { WorkerScriptController::WorkerScriptController(WorkerGlobalScope& workerGlobalScope) - : m_workerGlobalScope(workerGlobalScope) + : m_isolate(v8::Isolate::New()) + , m_workerGlobalScope(workerGlobalScope) , m_executionForbidden(false) , m_executionScheduledToTerminate(false) { - v8::Isolate* isolate = v8::Isolate::New(); - isolate->Enter(); - V8Initializer::initializeWorker(isolate); + m_isolate->Enter(); + V8Initializer::initializeWorker(m_isolate); v8::V8::Initialize(); - m_isolateHolder = adoptPtr(new gin::IsolateHolder(isolate)); - V8PerIsolateData* data = V8PerIsolateData::create(isolate); - m_domDataStore = adoptPtr(new DOMDataStore(WorkerWorld)); - data->setWorkerDOMDataStore(m_domDataStore.get()); + V8PerIsolateData::ensureInitialized(m_isolate); + m_world = DOMWrapperWorld::create(WorkerWorldId); + m_interruptor = adoptPtr(new V8IsolateInterruptor(m_isolate)); + ThreadState::current()->addInterruptor(m_interruptor.get()); } +// We need to postpone V8 Isolate destruction until the very end of +// worker thread finalization when all objects on the worker heap +// are destroyed. +class IsolateCleanupTask : public ThreadState::CleanupTask { +public: + static PassOwnPtr<IsolateCleanupTask> create(v8::Isolate* isolate) + { + return adoptPtr(new IsolateCleanupTask(isolate)); + } + + virtual void postCleanup() + { + V8PerIsolateData::dispose(m_isolate); + m_isolate->Exit(); + m_isolate->Dispose(); + } + +private: + explicit IsolateCleanupTask(v8::Isolate* isolate) : m_isolate(isolate) { } + + v8::Isolate* m_isolate; +}; + WorkerScriptController::~WorkerScriptController() { - m_domDataStore.clear(); + ThreadState::current()->removeInterruptor(m_interruptor.get()); + + m_world->dispose(); // The corresponding call to didStartWorkerRunLoop is in // WorkerThread::workerThread(). // See http://webkit.org/b/83104#c14 for why this is here. blink::Platform::current()->didStopWorkerRunLoop(blink::WebWorkerRunLoop(&m_workerGlobalScope.thread()->runLoop())); - disposeContext(); - V8PerIsolateData::dispose(isolate()); - v8::Isolate* v8Isolate = isolate(); - v8Isolate->Exit(); - m_isolateHolder.clear(); - v8Isolate->Dispose(); -} + if (isContextInitialized()) + m_scriptState->disposePerContextData(); -void WorkerScriptController::disposeContext() -{ - m_perContextData.clear(); - m_contextHolder.clear(); + ThreadState::current()->addCleanupTask(IsolateCleanupTask::create(m_isolate)); } bool WorkerScriptController::initializeContextIfNeeded() { - if (m_contextHolder) + v8::HandleScope handleScope(m_isolate); + + if (isContextInitialized()) return true; - v8::Handle<v8::Context> context = v8::Context::New(isolate()); + v8::Handle<v8::Context> context = v8::Context::New(m_isolate); if (context.IsEmpty()) return false; - m_contextHolder = adoptPtr(new gin::ContextHolder(isolate())); - m_contextHolder->SetContext(context); - - v8::Context::Scope scope(context); - - V8PerContextDataHolder::install(context); + m_scriptState = ScriptState::create(context, m_world); - m_perContextData = V8PerContextData::create(context); - if (!m_perContextData->init()) { - disposeContext(); - return false; - } + ScriptState::Scope scope(m_scriptState.get()); // Set DebugId for the new context. - context->SetEmbedderData(0, v8AtomicString(isolate(), "worker")); + context->SetEmbedderData(0, v8AtomicString(m_isolate, "worker")); // Create a new JS object and use it as the prototype for the shadow global object. const WrapperTypeInfo* contextType = &V8DedicatedWorkerGlobalScope::wrapperTypeInfo; @@ -126,17 +137,17 @@ bool WorkerScriptController::initializeContextIfNeeded() contextType = &V8ServiceWorkerGlobalScope::wrapperTypeInfo; else if (!m_workerGlobalScope.isDedicatedWorkerGlobalScope()) contextType = &V8SharedWorkerGlobalScope::wrapperTypeInfo; - v8::Handle<v8::Function> workerGlobalScopeConstructor = m_perContextData->constructorForType(contextType); - v8::Local<v8::Object> jsWorkerGlobalScope = V8ObjectConstructor::newInstance(workerGlobalScopeConstructor); + v8::Handle<v8::Function> workerGlobalScopeConstructor = m_scriptState->perContextData()->constructorForType(contextType); + v8::Local<v8::Object> jsWorkerGlobalScope = V8ObjectConstructor::newInstance(m_isolate, workerGlobalScopeConstructor); if (jsWorkerGlobalScope.IsEmpty()) { - disposeContext(); + m_scriptState->disposePerContextData(); return false; } - V8DOMWrapper::associateObjectWithWrapper<V8WorkerGlobalScope>(PassRefPtr<WorkerGlobalScope>(m_workerGlobalScope), contextType, jsWorkerGlobalScope, isolate(), WrapperConfiguration::Dependent); + V8DOMWrapper::associateObjectWithWrapper<V8WorkerGlobalScope>(PassRefPtrWillBeRawPtr<WorkerGlobalScope>(&m_workerGlobalScope), contextType, jsWorkerGlobalScope, m_isolate, WrapperConfiguration::Dependent); // Insert the object instance as the prototype of the shadow object. - v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_contextHolder->context()->Global()->GetPrototype()); + v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_scriptState->context()->Global()->GetPrototype()); globalObject->SetPrototype(jsWorkerGlobalScope); return true; @@ -144,25 +155,22 @@ bool WorkerScriptController::initializeContextIfNeeded() ScriptValue WorkerScriptController::evaluate(const String& script, const String& fileName, const TextPosition& scriptStartPosition, WorkerGlobalScopeExecutionState* state) { - v8::HandleScope handleScope(isolate()); - if (!initializeContextIfNeeded()) return ScriptValue(); - v8::Handle<v8::Context> context = m_contextHolder->context(); + ScriptState::Scope scope(m_scriptState.get()); + if (!m_disableEvalPending.isEmpty()) { - context->AllowCodeGenerationFromStrings(false); - context->SetErrorMessageForCodeGenerationFromStrings(v8String(isolate(), m_disableEvalPending)); + m_scriptState->context()->AllowCodeGenerationFromStrings(false); + m_scriptState->context()->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, m_disableEvalPending)); m_disableEvalPending = String(); } - v8::Context::Scope scope(context); - v8::TryCatch block; - v8::Handle<v8::String> scriptString = v8String(isolate(), script); - v8::Handle<v8::Script> compiledScript = V8ScriptRunner::compileScript(scriptString, fileName, scriptStartPosition, 0, isolate()); - v8::Local<v8::Value> result = V8ScriptRunner::runCompiledScript(compiledScript, &m_workerGlobalScope, isolate()); + v8::Handle<v8::String> scriptString = v8String(m_isolate, script); + v8::Handle<v8::Script> compiledScript = V8ScriptRunner::compileScript(scriptString, fileName, scriptStartPosition, 0, m_isolate); + v8::Local<v8::Value> result = V8ScriptRunner::runCompiledScript(compiledScript, &m_workerGlobalScope, m_isolate); if (!block.CanContinue()) { m_workerGlobalScope.script()->forbidExecution(); @@ -175,9 +183,9 @@ ScriptValue WorkerScriptController::evaluate(const String& script, const String& state->errorMessage = toCoreString(message->Get()); state->lineNumber = message->GetLineNumber(); state->columnNumber = message->GetStartColumn() + 1; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, sourceURL, message->GetScriptResourceName(), ScriptValue()); + TOSTRING_DEFAULT(V8StringResource<>, sourceURL, message->GetScriptResourceName(), ScriptValue()); state->sourceURL = sourceURL; - state->exception = ScriptValue(block.Exception(), isolate()); + state->exception = ScriptValue(m_scriptState.get(), block.Exception()); block.Reset(); } else state->hadException = false; @@ -185,10 +193,10 @@ ScriptValue WorkerScriptController::evaluate(const String& script, const String& if (result.IsEmpty() || result->IsUndefined()) return ScriptValue(); - return ScriptValue(result, isolate()); + return ScriptValue(m_scriptState.get(), result); } -void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, RefPtr<ErrorEvent>* errorEvent) +void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, RefPtrWillBeRawPtr<ErrorEvent>* errorEvent) { if (isExecutionForbidden()) return; @@ -198,12 +206,17 @@ void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, RefPtr if (state.hadException) { if (errorEvent) { *errorEvent = m_workerGlobalScope.shouldSanitizeScriptError(state.sourceURL, NotSharableCrossOrigin) ? - ErrorEvent::createSanitizedError(0) : ErrorEvent::create(state.errorMessage, state.sourceURL, state.lineNumber, state.columnNumber, 0); - V8ErrorHandler::storeExceptionOnErrorEventWrapper(errorEvent->get(), state.exception.v8Value(), isolate()); + ErrorEvent::createSanitizedError(m_world.get()) : ErrorEvent::create(state.errorMessage, state.sourceURL, state.lineNumber, state.columnNumber, m_world.get()); + V8ErrorHandler::storeExceptionOnErrorEventWrapper(errorEvent->get(), state.exception.v8Value(), m_scriptState->context()->Global(), m_isolate); } else { ASSERT(!m_workerGlobalScope.shouldSanitizeScriptError(state.sourceURL, NotSharableCrossOrigin)); - RefPtr<ErrorEvent> event = m_errorEventFromImportedScript ? m_errorEventFromImportedScript.release() : ErrorEvent::create(state.errorMessage, state.sourceURL, state.lineNumber, state.columnNumber, 0); - m_workerGlobalScope.reportException(event, 0, NotSharableCrossOrigin); + RefPtrWillBeRawPtr<ErrorEvent> event = nullptr; + if (m_errorEventFromImportedScript) { + event = m_errorEventFromImportedScript.release(); + } else { + event = ErrorEvent::create(state.errorMessage, state.sourceURL, state.lineNumber, state.columnNumber, m_world.get()); + } + m_workerGlobalScope.reportException(event, nullptr, NotSharableCrossOrigin); } } } @@ -217,7 +230,7 @@ void WorkerScriptController::scheduleExecutionTermination() MutexLocker locker(m_scheduledTerminationMutex); m_executionScheduledToTerminate = true; } - v8::V8::TerminateExecution(isolate()); + v8::V8::TerminateExecution(m_isolate); } bool WorkerScriptController::isExecutionTerminating() const @@ -244,26 +257,10 @@ void WorkerScriptController::disableEval(const String& errorMessage) m_disableEvalPending = errorMessage; } -void WorkerScriptController::rethrowExceptionFromImportedScript(PassRefPtr<ErrorEvent> errorEvent) +void WorkerScriptController::rethrowExceptionFromImportedScript(PassRefPtrWillBeRawPtr<ErrorEvent> errorEvent) { m_errorEventFromImportedScript = errorEvent; - throwError(V8ThrowException::createError(v8GeneralError, m_errorEventFromImportedScript->message(), isolate()), isolate()); -} - -WorkerScriptController* WorkerScriptController::controllerForContext() -{ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - // Happens on frame destruction, check otherwise GetCurrent() will crash. - if (!isolate || !isolate->InContext()) - return 0; - v8::Handle<v8::Context> context = isolate->GetCurrentContext(); - v8::Handle<v8::Object> global = context->Global(); - global = global->FindInstanceInPrototypeChain(V8WorkerGlobalScope::domTemplate(isolate, WorkerWorld)); - // Return 0 if the current executing context is not the worker context. - if (global.IsEmpty()) - return 0; - WorkerGlobalScope* workerGlobalScope = V8WorkerGlobalScope::toNative(global); - return workerGlobalScope->script(); + throwError(V8ThrowException::createError(v8GeneralError, m_errorEventFromImportedScript->message(), m_isolate), m_isolate); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.h b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.h index 7b7ea1af507..2559269fdd0 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.h @@ -34,17 +34,11 @@ #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "core/events/ErrorEvent.h" -#include "gin/public/context_holder.h" -#include "gin/public/isolate_holder.h" #include "wtf/OwnPtr.h" #include "wtf/ThreadingPrimitives.h" #include "wtf/text/TextPosition.h" #include <v8.h> -namespace gin { -class IsolateHolder; -} - namespace WebCore { class ScriptSourceCode; @@ -74,9 +68,11 @@ namespace WebCore { WorkerGlobalScope& workerGlobalScope() { return m_workerGlobalScope; } - void evaluate(const ScriptSourceCode&, RefPtr<ErrorEvent>* = 0); + bool initializeContextIfNeeded(); + + void evaluate(const ScriptSourceCode&, RefPtrWillBeRawPtr<ErrorEvent>* = 0); - void rethrowExceptionFromImportedScript(PassRefPtr<ErrorEvent>); + void rethrowExceptionFromImportedScript(PassRefPtrWillBeRawPtr<ErrorEvent>); // Async request to terminate a future JS execution. Eventually causes termination // exception raised during JS execution, if the worker thread happens to run JS. @@ -93,36 +89,32 @@ namespace WebCore { void disableEval(const String&); - // Returns WorkerScriptController for the currently executing context. 0 will be returned if the current executing context is not the worker context. - static WorkerScriptController* controllerForContext(); - // Evaluate a script file in the current execution environment. ScriptValue evaluate(const String& script, const String& fileName, const TextPosition& scriptStartPosition, WorkerGlobalScopeExecutionState*); - // Returns a local handle of the context. - v8::Local<v8::Context> context() { return m_contextHolder ? m_contextHolder->context() : v8::Local<v8::Context>(); } + v8::Isolate* isolate() const { return m_isolate; } + DOMWrapperWorld& world() const { return *m_world; } + ScriptState* scriptState() { return m_scriptState.get(); } + v8::Local<v8::Context> context() { return m_scriptState ? m_scriptState->context() : v8::Local<v8::Context>(); } + bool isContextInitialized() { return m_scriptState && !!m_scriptState->perContextData(); } // Send a notification about current thread is going to be idle. // Returns true if the embedder should stop calling idleNotification // until real work has been done. bool idleNotification() { return v8::V8::IdleNotification(); } - v8::Isolate* isolate() const { return m_isolateHolder->isolate(); } private: - bool initializeContextIfNeeded(); - void disposeContext(); - + v8::Isolate* m_isolate; WorkerGlobalScope& m_workerGlobalScope; - OwnPtr<gin::IsolateHolder> m_isolateHolder; - OwnPtr<gin::ContextHolder> m_contextHolder; - OwnPtr<V8PerContextData> m_perContextData; + RefPtr<ScriptState> m_scriptState; + RefPtr<DOMWrapperWorld> m_world; String m_disableEvalPending; - OwnPtr<DOMDataStore> m_domDataStore; bool m_executionForbidden; bool m_executionScheduledToTerminate; mutable Mutex m_scheduledTerminationMutex; - RefPtr<ErrorEvent> m_errorEventFromImportedScript; + RefPtrWillBePersistent<ErrorEvent> m_errorEventFromImportedScript; + OwnPtr<V8IsolateInterruptor> m_interruptor; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.cpp b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.cpp index 935a2d26dc5..920508e1e43 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.cpp @@ -42,11 +42,10 @@ namespace WebCore { -WorkerScriptDebugServer::WorkerScriptDebugServer(WorkerGlobalScope* workerGlobalScope, const String& mode) +WorkerScriptDebugServer::WorkerScriptDebugServer(WorkerGlobalScope* workerGlobalScope) : ScriptDebugServer(v8::Isolate::GetCurrent()) , m_listener(0) , m_workerGlobalScope(workerGlobalScope) - , m_debuggerTaskMode(mode) { ASSERT(m_isolate); } @@ -54,16 +53,17 @@ WorkerScriptDebugServer::WorkerScriptDebugServer(WorkerGlobalScope* workerGlobal void WorkerScriptDebugServer::addListener(ScriptDebugListener* listener) { v8::HandleScope scope(m_isolate); - v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); - v8::Context::Scope contextScope(debuggerContext); - ASSERT(!m_listener); - m_listener = listener; + v8::Debug::SetDebugEventListener(&WorkerScriptDebugServer::v8DebugEventCallback, v8::External::New(m_isolate, this)); ensureDebuggerScriptCompiled(); + m_listener = listener; + + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + v8::Local<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isolate); ASSERT(!debuggerScript->IsUndefined()); - v8::Debug::SetDebugEventListener2(&WorkerScriptDebugServer::v8DebugEventCallback, v8::External::New(m_isolate, this)); v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(debuggerScript->Get(v8AtomicString(m_isolate, "getWorkerScripts"))); v8::Handle<v8::Value> value = V8ScriptRunner::callInternalFunction(getScriptsFunction, debuggerScript, 0, 0, m_isolate); @@ -72,15 +72,16 @@ void WorkerScriptDebugServer::addListener(ScriptDebugListener* listener) ASSERT(!value->IsUndefined() && value->IsArray()); v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value); for (unsigned i = 0; i < scriptsArray->Length(); ++i) - dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i, m_isolate)))); + dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(m_isolate, i)))); } void WorkerScriptDebugServer::removeListener(ScriptDebugListener* listener) { ASSERT(m_listener == listener); continueProgram(); + discardDebuggerScript(); m_listener = 0; - v8::Debug::SetDebugEventListener2(0); + v8::Debug::SetDebugEventListener(0); } void WorkerScriptDebugServer::interruptAndRunTask(PassOwnPtr<Task> task) @@ -98,7 +99,7 @@ void WorkerScriptDebugServer::runMessageLoopOnPause(v8::Handle<v8::Context>) { MessageQueueWaitResult result; do { - result = m_workerGlobalScope->thread()->runLoop().runInMode(m_workerGlobalScope, m_debuggerTaskMode); + result = m_workerGlobalScope->thread()->runLoop().runDebuggerTask(); // Keep waiting until execution is resumed. } while (result == MessageQueueMessageReceived && isPaused()); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.h b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.h index befaaa90942..81fde7da0e5 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.h @@ -32,21 +32,18 @@ #define WorkerScriptDebugServer_h #include "bindings/v8/ScriptDebugServer.h" - -namespace v8 { -class Isolate; -} +#include <v8.h> namespace WebCore { class WorkerGlobalScope; class WorkerThread; -class WorkerScriptDebugServer : public ScriptDebugServer { +class WorkerScriptDebugServer FINAL : public ScriptDebugServer { WTF_MAKE_NONCOPYABLE(WorkerScriptDebugServer); public: - WorkerScriptDebugServer(WorkerGlobalScope*, const String&); - ~WorkerScriptDebugServer() { } + explicit WorkerScriptDebugServer(WorkerGlobalScope*); + virtual ~WorkerScriptDebugServer() { } void addListener(ScriptDebugListener*); void removeListener(ScriptDebugListener*); @@ -54,14 +51,13 @@ public: void interruptAndRunTask(PassOwnPtr<Task>); private: - virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>); - virtual void runMessageLoopOnPause(v8::Handle<v8::Context>); - virtual void quitMessageLoopOnPause(); + virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>) OVERRIDE; + virtual void runMessageLoopOnPause(v8::Handle<v8::Context>) OVERRIDE; + virtual void quitMessageLoopOnPause() OVERRIDE; typedef HashMap<WorkerGlobalScope*, ScriptDebugListener*> ListenersMap; ScriptDebugListener* m_listener; WorkerGlobalScope* m_workerGlobalScope; - String m_debuggerTaskMode; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/WrapperTypeInfo.h b/chromium/third_party/WebKit/Source/bindings/v8/WrapperTypeInfo.h index 227083d018b..3d92f6adb0d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/WrapperTypeInfo.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/WrapperTypeInfo.h @@ -32,13 +32,13 @@ #define WrapperTypeInfo_h #include "gin/public/wrapper_info.h" +#include "platform/heap/Handle.h" #include "wtf/Assertions.h" #include <v8.h> namespace WebCore { class ActiveDOMObject; - class DOMDataStore; class EventTarget; class Node; @@ -51,13 +51,7 @@ namespace WebCore { static const uint16_t v8DOMNodeClassId = 1; static const uint16_t v8DOMObjectClassId = 2; - enum WrapperWorldType { - MainWorld, - IsolatedWorld, - WorkerWorld - }; - - typedef v8::Handle<v8::FunctionTemplate> (*DomTemplateFunction)(v8::Isolate*, WrapperWorldType); + typedef v8::Handle<v8::FunctionTemplate> (*DomTemplateFunction)(v8::Isolate*); typedef void (*DerefObjectFunction)(void*); typedef ActiveDOMObject* (*ToActiveDOMObjectFunction)(v8::Handle<v8::Object>); typedef EventTarget* (*ToEventTargetFunction)(v8::Handle<v8::Object>); @@ -66,7 +60,13 @@ namespace WebCore { enum WrapperTypePrototype { WrapperTypeObjectPrototype, - WrapperTypeErrorPrototype + WrapperTypeExceptionPrototype + }; + + enum GCType { + GarbageCollectedObject, + WillBeGarbageCollectedObject, + RefCountedObject, }; inline void setObjectGroup(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) @@ -100,12 +100,9 @@ namespace WebCore { return false; } - v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate* isolate, WrapperWorldType worldType) const { return domTemplateFunction(isolate, worldType); } - - void derefObject(void* object) const + v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate* isolate) const { - if (derefObjectFunction) - derefObjectFunction(object); + return domTemplateFunction(isolate); } void installPerContextEnabledMethods(v8::Handle<v8::Object> prototypeTemplate, v8::Isolate* isolate) const @@ -147,6 +144,7 @@ namespace WebCore { const InstallPerContextEnabledPrototypePropertiesFunction installPerContextEnabledMethodsFunction; const WrapperTypeInfo* parentClass; const WrapperTypePrototype wrapperTypePrototype; + const GCType gcType; }; @@ -162,30 +160,60 @@ namespace WebCore { } template<typename T, int offset> - inline T* getInternalField(v8::Handle<v8::Object> object) + inline T* getInternalField(v8::Handle<v8::Object> wrapper) { - ASSERT(offset < object->InternalFieldCount()); - return static_cast<T*>(object->GetAlignedPointerFromInternalField(offset)); + ASSERT(offset < wrapper->InternalFieldCount()); + return static_cast<T*>(wrapper->GetAlignedPointerFromInternalField(offset)); + } + + inline void* toNative(const v8::Persistent<v8::Object>& wrapper) + { + return getInternalField<void, v8DOMWrapperObjectIndex>(wrapper); + } + + inline void* toNative(v8::Handle<v8::Object> wrapper) + { + return getInternalField<void, v8DOMWrapperObjectIndex>(wrapper); } - inline void* toNative(const v8::Persistent<v8::Object>& object) + inline const WrapperTypeInfo* toWrapperTypeInfo(const v8::Persistent<v8::Object>& wrapper) { - return getInternalField<void, v8DOMWrapperObjectIndex>(object); + return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(wrapper); } - inline void* toNative(v8::Handle<v8::Object> object) + inline const WrapperTypeInfo* toWrapperTypeInfo(v8::Handle<v8::Object> wrapper) { - return getInternalField<void, v8DOMWrapperObjectIndex>(object); + return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(wrapper); } - inline const WrapperTypeInfo* toWrapperTypeInfo(const v8::Persistent<v8::Object>& object) + inline const PersistentNode* toPersistentHandle(const v8::Handle<v8::Object>& wrapper) { - return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(object); + // Persistent handle is stored in the last internal field. + return static_cast<PersistentNode*>(wrapper->GetAlignedPointerFromInternalField(wrapper->InternalFieldCount() - 1)); } - inline const WrapperTypeInfo* toWrapperTypeInfo(v8::Handle<v8::Object> object) + inline void releaseObject(v8::Handle<v8::Object> wrapper) { - return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(object); + const WrapperTypeInfo* typeInfo = toWrapperTypeInfo(wrapper); + if (typeInfo->gcType == GarbageCollectedObject) { + const PersistentNode* handle = toPersistentHandle(wrapper); + // This will be null iff a wrapper for a hidden wrapper object, + // see V8DOMWrapper::setNativeInfoForHiddenWrapper(). + delete handle; + } else if (typeInfo->gcType == WillBeGarbageCollectedObject) { +#if ENABLE(OILPAN) + const PersistentNode* handle = toPersistentHandle(wrapper); + // This will be null iff a wrapper for a hidden wrapper object, + // see V8DOMWrapper::setNativeInfoForHiddenWrapper(). + delete handle; +#else + ASSERT(typeInfo->derefObjectFunction); + typeInfo->derefObjectFunction(toNative(wrapper)); +#endif + } else { + ASSERT(typeInfo->derefObjectFunction); + typeInfo->derefObjectFunction(toNative(wrapper)); + } } struct WrapperConfiguration { @@ -194,7 +222,7 @@ namespace WebCore { Dependent, Independent }; - void configureWrapper(v8::Persistent<v8::Object>* wrapper) const + void configureWrapper(v8::PersistentBase<v8::Object>* wrapper) const { wrapper->SetWrapperClassId(classId); if (lifetime == Independent) @@ -216,11 +244,6 @@ namespace WebCore { WrapperConfiguration configuration = {v8DOMNodeClassId, lifetime}; return configuration; } - - template<class ElementType> - class WrapperTypeTraits { - // specialized classes have thier own functions, which are generated by binding generator. - }; } #endif // WrapperTypeInfo_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AlgorithmCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AlgorithmCustom.cpp deleted file mode 100644 index c8c4ccaa0e8..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AlgorithmCustom.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8Algorithm.h" - -#include "V8AesCbcParams.h" -#include "V8AesCtrParams.h" -#include "V8AesKeyGenParams.h" -#include "V8HmacKeyParams.h" -#include "V8HmacParams.h" -#include "V8RsaKeyGenParams.h" -#include "V8RsaSsaParams.h" -#include "platform/NotImplemented.h" - -namespace WebCore { - -v8::Handle<v8::Object> wrap(Algorithm* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(impl); - - // Wrap as the more derived type. - switch (impl->type()) { - case blink::WebCryptoAlgorithmParamsTypeNone: - return V8Algorithm::createWrapper(impl, creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeAesCbcParams: - return wrap(static_cast<AesCbcParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams: - return wrap(static_cast<AesKeyGenParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeHmacParams: - return wrap(static_cast<HmacParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeHmacKeyParams: - return wrap(static_cast<HmacKeyParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeRsaSsaParams: - return wrap(static_cast<RsaSsaParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams: - return wrap(static_cast<RsaKeyGenParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeAesCtrParams: - return wrap(static_cast<AesCtrParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeAesGcmParams: - case blink::WebCryptoAlgorithmParamsTypeRsaOaepParams: - // TODO - notImplemented(); - break; - } - - ASSERT_NOT_REACHED(); - return v8::Handle<v8::Object>(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp index 8eb4c2b818d..f3494cf694e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" -#include "bindings/v8/ScriptPromiseResolver.h" #include "bindings/v8/V8Binding.h" #include "wtf/ArrayBuffer.h" #include "wtf/StdLibExtras.h" @@ -49,15 +48,10 @@ V8ArrayBufferDeallocationObserver* V8ArrayBufferDeallocationObserver::instanceTe const WrapperTypeInfo V8ArrayBuffer::wrapperTypeInfo = { gin::kEmbedderBlink, 0, V8ArrayBuffer::derefObject, - 0, 0, 0, 0, 0, WrapperTypeObjectPrototype + 0, 0, 0, 0, 0, WrapperTypeObjectPrototype, RefCountedObject }; -bool V8ArrayBuffer::hasInstance(v8::Handle<v8::Value> value, v8::Isolate*, WrapperWorldType) -{ - return value->IsArrayBuffer(); -} - -bool V8ArrayBuffer::hasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isolate*) +bool V8ArrayBuffer::hasInstance(v8::Handle<v8::Value> value, v8::Isolate*) { return value->IsArrayBuffer(); } @@ -82,12 +76,11 @@ v8::Handle<v8::Object> V8ArrayBuffer::createWrapper(PassRefPtr<ArrayBuffer> impl ArrayBuffer* V8ArrayBuffer::toNative(v8::Handle<v8::Object> object) { ASSERT(object->IsArrayBuffer()); - void* arraybufferPtr = object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex); - if (arraybufferPtr) - return reinterpret_cast<ArrayBuffer*>(arraybufferPtr); - v8::Local<v8::ArrayBuffer> v8buffer = object.As<v8::ArrayBuffer>(); - ASSERT(!v8buffer->IsExternal()); + if (v8buffer->IsExternal()) { + RELEASE_ASSERT(toWrapperTypeInfo(object)->ginEmbedder == gin::kEmbedderBlink); + return reinterpret_cast<ArrayBuffer*>(WebCore::toNative(object)); + } v8::ArrayBuffer::Contents v8Contents = v8buffer->Externalize(); ArrayBufferContents contents(v8Contents.Data(), v8Contents.ByteLength(), @@ -95,9 +88,12 @@ ArrayBuffer* V8ArrayBuffer::toNative(v8::Handle<v8::Object> object) RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(contents); V8DOMWrapper::associateObjectWithWrapper<V8ArrayBuffer>(buffer.release(), &wrapperTypeInfo, object, v8::Isolate::GetCurrent(), WrapperConfiguration::Dependent); - arraybufferPtr = object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex); - ASSERT(arraybufferPtr); - return reinterpret_cast<ArrayBuffer*>(arraybufferPtr); + return reinterpret_cast<ArrayBuffer*>(WebCore::toNative(object)); +} + +ArrayBuffer* V8ArrayBuffer::toNativeWithTypeCheck(v8::Isolate* isolate, v8::Handle<v8::Value> value) +{ + return V8ArrayBuffer::hasInstance(value, isolate) ? V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(value)) : 0; } template<> diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.h index 2c5ff8e1cac..779095f7c9a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.h @@ -34,9 +34,9 @@ namespace WebCore { -class V8ArrayBufferDeallocationObserver: public WTF::ArrayBufferDeallocationObserver { +class V8ArrayBufferDeallocationObserver FINAL: public WTF::ArrayBufferDeallocationObserver { public: - virtual void arrayBufferDeallocated(unsigned sizeInBytes) + virtual void arrayBufferDeallocated(unsigned sizeInBytes) OVERRIDE { v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-static_cast<int>(sizeInBytes)); } @@ -51,9 +51,9 @@ protected: class V8ArrayBuffer { public: - static bool hasInstance(v8::Handle<v8::Value>, v8::Isolate*, WrapperWorldType); - static bool hasInstanceInAnyWorld(v8::Handle<v8::Value>, v8::Isolate*); + static bool hasInstance(v8::Handle<v8::Value>, v8::Isolate*); static ArrayBuffer* toNative(v8::Handle<v8::Object>); + static ArrayBuffer* toNativeWithTypeCheck(v8::Isolate*, v8::Handle<v8::Value>); static void derefObject(void*); static const WrapperTypeInfo wrapperTypeInfo; static const int internalFieldCount = v8DefaultWrapperInternalFieldCount; @@ -75,13 +75,6 @@ private: static v8::Handle<v8::Object> createWrapper(PassRefPtr<ArrayBuffer>, v8::Handle<v8::Object> creationContext, v8::Isolate*); }; -template<> -class WrapperTypeTraits<ArrayBuffer > { -public: - static const WrapperTypeInfo* wrapperTypeInfo() { return &V8ArrayBuffer::wrapperTypeInfo; } -}; - - inline v8::Handle<v8::Object> wrap(ArrayBuffer* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { ASSERT(impl); @@ -115,7 +108,7 @@ inline void v8SetReturnValue(const CallbackInfo& info, ArrayBuffer* impl) template<class CallbackInfo> inline void v8SetReturnValueForMainWorld(const CallbackInfo& info, ArrayBuffer* impl) { - ASSERT(worldType(info.GetIsolate()) == MainWorld); + ASSERT(DOMWrapperWorld::current(info.GetIsolate()).isMainWorld()); if (UNLIKELY(!impl)) { v8SetReturnValueNull(info); return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.cpp index 4f00d0df933..5ee873dd6cb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.cpp @@ -82,5 +82,9 @@ ArrayBufferView* V8ArrayBufferView::toNative(v8::Handle<v8::Object> object) return 0; } +ArrayBufferView* V8ArrayBufferView::toNativeWithTypeCheck(v8::Isolate* isolate, v8::Handle<v8::Value> value) +{ + return V8ArrayBufferView::hasInstance(value, isolate) ? V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(value)) : 0; +} } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h index 94fcd1344d8..7ff95bf68ee 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h @@ -43,15 +43,12 @@ namespace WebCore { class V8ArrayBufferView { public: - static bool hasInstance(v8::Handle<v8::Value> value, v8::Isolate*, WrapperWorldType) - { - return value->IsArrayBufferView(); - } - static bool hasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isolate*) + static bool hasInstance(v8::Handle<v8::Value> value, v8::Isolate*) { return value->IsArrayBufferView(); } static ArrayBufferView* toNative(v8::Handle<v8::Object>); + static ArrayBufferView* toNativeWithTypeCheck(v8::Isolate*, v8::Handle<v8::Value>); static inline void* toInternalPointer(ArrayBufferView* impl) { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustomScript.js b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustomScript.js deleted file mode 100644 index d3448599a90..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustomScript.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -(function() { - return function(source, length, offset) { - if (offset == 0) { - for (var i = 0; i < length; i++) - this[i] = source[i]; - } else { - for (var i = 0; i < length; i++) - this[i + offset] = source[i]; - } - } -})(); - diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AudioNodeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AudioNodeCustom.cpp index fcc9d085027..762b58580fb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AudioNodeCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AudioNodeCustom.cpp @@ -24,25 +24,25 @@ #include "config.h" #if ENABLE(WEB_AUDIO) -#include "V8AudioNode.h" +#include "bindings/modules/v8/V8AudioNode.h" -#include "V8AnalyserNode.h" -#include "V8AudioBufferSourceNode.h" -#include "V8AudioDestinationNode.h" -#include "V8BiquadFilterNode.h" -#include "V8ChannelMergerNode.h" -#include "V8ChannelSplitterNode.h" -#include "V8ConvolverNode.h" -#include "V8DelayNode.h" -#include "V8DynamicsCompressorNode.h" -#include "V8GainNode.h" -#include "V8MediaElementAudioSourceNode.h" -#include "V8MediaStreamAudioDestinationNode.h" -#include "V8MediaStreamAudioSourceNode.h" -#include "V8OscillatorNode.h" -#include "V8PannerNode.h" -#include "V8ScriptProcessorNode.h" -#include "V8WaveShaperNode.h" +#include "bindings/modules/v8/V8AnalyserNode.h" +#include "bindings/modules/v8/V8AudioBufferSourceNode.h" +#include "bindings/modules/v8/V8AudioDestinationNode.h" +#include "bindings/modules/v8/V8BiquadFilterNode.h" +#include "bindings/modules/v8/V8ChannelMergerNode.h" +#include "bindings/modules/v8/V8ChannelSplitterNode.h" +#include "bindings/modules/v8/V8ConvolverNode.h" +#include "bindings/modules/v8/V8DelayNode.h" +#include "bindings/modules/v8/V8DynamicsCompressorNode.h" +#include "bindings/modules/v8/V8GainNode.h" +#include "bindings/modules/v8/V8MediaElementAudioSourceNode.h" +#include "bindings/modules/v8/V8MediaStreamAudioDestinationNode.h" +#include "bindings/modules/v8/V8MediaStreamAudioSourceNode.h" +#include "bindings/modules/v8/V8OscillatorNode.h" +#include "bindings/modules/v8/V8PannerNode.h" +#include "bindings/modules/v8/V8ScriptProcessorNode.h" +#include "bindings/modules/v8/V8WaveShaperNode.h" #include "bindings/v8/V8Binding.h" #include "modules/webaudio/AnalyserNode.h" #include "modules/webaudio/AudioBufferSourceNode.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BiquadFilterNodeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BiquadFilterNodeCustom.cpp deleted file mode 100644 index 862d040c3b4..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BiquadFilterNodeCustom.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2012, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#if ENABLE(WEB_AUDIO) -#include "V8BiquadFilterNode.h" - -#include "bindings/v8/V8Binding.h" -#include "modules/webaudio/BiquadFilterNode.h" - -namespace WebCore { - -void V8BiquadFilterNode::typeAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - BiquadFilterNode* imp = V8BiquadFilterNode::toNative(info.Holder()); - - if (value->IsNumber()) { - bool ok = false; - uint32_t type = toUInt32(value, ok); - ASSERT(ok); - if (!imp->setType(type)) - throwTypeError("Illegal BiquadFilterNode type", info.GetIsolate()); - return; - } - - if (value->IsString()) { - String type = toCoreString(value.As<v8::String>()); - if (type == "lowpass" || type == "highpass" || type == "bandpass" || type == "lowshelf" || type == "highshelf" || type == "peaking" || type == "notch" || type == "allpass") { - imp->setType(type); - return; - } - } - - throwTypeError("Illegal BiquadFilterNode type", info.GetIsolate()); -} - -} // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp index db9fbbb4295..594b9772cbd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp @@ -29,11 +29,10 @@ */ #include "config.h" -#include "V8Blob.h" +#include "bindings/core/v8/V8Blob.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/custom/V8BlobCustomHelpers.h" -#include "core/fileapi/BlobBuilder.h" namespace WebCore { @@ -41,7 +40,7 @@ void V8Blob::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ConstructionContext, "Blob", info.Holder(), info.GetIsolate()); if (!info.Length()) { - RefPtr<Blob> blob = Blob::create(); + RefPtrWillBeRawPtr<Blob> blob = Blob::create(); v8SetReturnValue(info, blob.release()); return; } @@ -72,12 +71,14 @@ void V8Blob::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) } } - BlobBuilder blobBuilder; + OwnPtr<BlobData> blobData = BlobData::create(); + blobData->setContentType(properties.contentType()); v8::Local<v8::Object> blobParts = v8::Local<v8::Object>::Cast(info[0]); - if (!V8BlobCustomHelpers::processBlobParts(blobParts, length, properties.endings(), blobBuilder, info.GetIsolate())) + if (!V8BlobCustomHelpers::processBlobParts(blobParts, length, properties.normalizeLineEndingsToNative(), *blobData, info.GetIsolate())) return; - RefPtr<Blob> blob = blobBuilder.createBlob(properties.contentType()); + long long blobSize = blobData->length(); + RefPtrWillBeRawPtr<Blob> blob = Blob::create(BlobDataHandle::create(blobData.release(), blobSize)); v8SetReturnValue(info, blob.release()); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp index 62bdc36e7b2..e6ec3535ba6 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp @@ -29,16 +29,14 @@ */ #include "config.h" -#include "V8BlobCustomHelpers.h" +#include "bindings/v8/custom/V8BlobCustomHelpers.h" -#include "V8Blob.h" +#include "bindings/core/v8/V8Blob.h" #include "bindings/v8/Dictionary.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" -#include "core/fileapi/BlobBuilder.h" #include "wtf/DateMath.h" namespace WebCore { @@ -46,7 +44,7 @@ namespace WebCore { namespace V8BlobCustomHelpers { ParsedProperties::ParsedProperties(bool hasFileProperties) - : m_endings("transparent") + : m_normalizeLineEndingsToNative(false) , m_hasFileProperties(hasFileProperties) #ifndef NDEBUG , m_hasLastModified(false) @@ -71,19 +69,20 @@ void ParsedProperties::setDefaultLastModified() bool ParsedProperties::parseBlobPropertyBag(v8::Local<v8::Value> propertyBag, const char* blobClassName, ExceptionState& exceptionState, v8::Isolate* isolate) { - ASSERT(m_endings == "transparent"); + TONATIVE_DEFAULT(Dictionary, dictionary, Dictionary(propertyBag, isolate), false); - V8TRYCATCH_RETURN(Dictionary, dictionary, Dictionary(propertyBag, isolate), false); - - V8TRYCATCH_RETURN(bool, containsEndings, dictionary.get("endings", m_endings), false); + String endings; + TONATIVE_DEFAULT(bool, containsEndings, dictionary.get("endings", endings), false); if (containsEndings) { - if (m_endings != "transparent" && m_endings != "native") { + if (endings != "transparent" && endings != "native") { exceptionState.throwTypeError("The 'endings' property must be either 'transparent' or 'native'."); return false; } + if (endings == "native") + m_normalizeLineEndingsToNative = true; } - V8TRYCATCH_RETURN(bool, containsType, dictionary.get("type", m_contentType), false); + TONATIVE_DEFAULT(bool, containsType, dictionary.get("type", m_contentType), false); if (containsType) { if (!m_contentType.containsOnlyASCII()) { exceptionState.throwDOMException(SyntaxError, "The 'type' property must consist of ASCII characters."); @@ -96,9 +95,9 @@ bool ParsedProperties::parseBlobPropertyBag(v8::Local<v8::Value> propertyBag, co return true; v8::Local<v8::Value> lastModified; - V8TRYCATCH_RETURN(bool, containsLastModified, dictionary.get("lastModified", lastModified), false); + TONATIVE_DEFAULT(bool, containsLastModified, dictionary.get("lastModified", lastModified), false); if (containsLastModified) { - V8TRYCATCH_RETURN(long long, lastModifiedInt, toInt64(lastModified), false); + TONATIVE_DEFAULT(long long, lastModifiedInt, toInt64(lastModified), false); setLastModified(static_cast<double>(lastModifiedInt) / msPerSecond); } else { setDefaultLastModified(); @@ -107,30 +106,28 @@ bool ParsedProperties::parseBlobPropertyBag(v8::Local<v8::Value> propertyBag, co return true; } -bool processBlobParts(v8::Local<v8::Object> blobParts, uint32_t blobPartsLength, const String& endings, BlobBuilder& blobBuilder, v8::Isolate* isolate) +bool processBlobParts(v8::Local<v8::Object> blobParts, uint32_t blobPartsLength, bool normalizeLineEndingsToNative, BlobData& blobData, v8::Isolate* isolate) { - ASSERT(endings == "transparent" || endings == "native"); - for (uint32_t i = 0; i < blobPartsLength; ++i) { - v8::Local<v8::Value> item = blobParts->Get(v8::Uint32::New(i, isolate)); + v8::Local<v8::Value> item = blobParts->Get(v8::Uint32::New(isolate, i)); if (item.IsEmpty()) return false; - if (V8ArrayBuffer::hasInstance(item, isolate, worldType(isolate))) { + if (V8ArrayBuffer::hasInstance(item, isolate)) { ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(item)); ASSERT(arrayBuffer); - blobBuilder.append(arrayBuffer); - } else if (V8ArrayBufferView::hasInstance(item, isolate, worldType(isolate))) { + blobData.appendArrayBuffer(arrayBuffer); + } else if (V8ArrayBufferView::hasInstance(item, isolate)) { ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(item)); ASSERT(arrayBufferView); - blobBuilder.append(arrayBufferView); - } else if (V8Blob::hasInstance(item, isolate, worldType(isolate))) { + blobData.appendArrayBufferView(arrayBufferView); + } else if (V8Blob::hasInstance(item, isolate)) { Blob* blob = V8Blob::toNative(v8::Handle<v8::Object>::Cast(item)); ASSERT(blob); - blobBuilder.append(blob); + blob->appendTo(blobData); } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, item, false); - blobBuilder.append(stringValue, endings); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, item, false); + blobData.appendText(stringValue, normalizeLineEndingsToNative); } } return true; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h index 37a173120bb..93cc08dce79 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h @@ -35,7 +35,7 @@ namespace WebCore { -class BlobBuilder; +class BlobData; class ExceptionState; // Shared code between the custom constructor bindings for Blob and File. @@ -53,7 +53,7 @@ public: explicit ParsedProperties(bool hasFileProperties); const String& contentType() const { return m_contentType; } - const String& endings() const { return m_endings; } + bool normalizeLineEndingsToNative() const { return m_normalizeLineEndingsToNative; } void setLastModified(double); void setDefaultLastModified(); double lastModified() const @@ -70,7 +70,7 @@ public: private: String m_contentType; - String m_endings; + bool m_normalizeLineEndingsToNative; // False if this contains the properties of a BlobPropertyBag. bool m_hasFileProperties; @@ -81,10 +81,10 @@ private: #endif // NDEBUG }; -// Appends the blobParts passed to a Blob or File constructor into a BlobBuilder. +// Appends the blobParts passed to a Blob or File constructor into a BlobData. // http://www.w3.org/TR/FileAPI/#constructorParams // Returns true if everything went well, false if a JS exception was thrown. -bool processBlobParts(v8::Local<v8::Object> blobParts, uint32_t blobPartsLength, const String& endings, BlobBuilder&, v8::Isolate*); +bool processBlobParts(v8::Local<v8::Object> blobParts, uint32_t blobPartsLength, bool normalizeLineEndingsToNative, BlobData&, v8::Isolate*); } // namespace V8BlobCustomHelpers diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSRuleCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSRuleCustom.cpp index 0fbd080bbd4..4aff8aa4090 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSRuleCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSRuleCustom.cpp @@ -29,20 +29,19 @@ */ #include "config.h" -#include "V8CSSRule.h" +#include "bindings/core/v8/V8CSSRule.h" -#include "V8CSSCharsetRule.h" -#include "V8CSSFontFaceRule.h" -#include "V8CSSImportRule.h" -#include "V8CSSKeyframeRule.h" -#include "V8CSSKeyframesRule.h" -#include "V8CSSMediaRule.h" -#include "V8CSSPageRule.h" -#include "V8CSSStyleRule.h" -#include "V8CSSSupportsRule.h" -#include "V8CSSViewportRule.h" -#include "V8WebKitCSSFilterRule.h" -#include "V8WebKitCSSRegionRule.h" +#include "bindings/core/v8/V8CSSCharsetRule.h" +#include "bindings/core/v8/V8CSSFontFaceRule.h" +#include "bindings/core/v8/V8CSSImportRule.h" +#include "bindings/core/v8/V8CSSKeyframeRule.h" +#include "bindings/core/v8/V8CSSKeyframesRule.h" +#include "bindings/core/v8/V8CSSMediaRule.h" +#include "bindings/core/v8/V8CSSPageRule.h" +#include "bindings/core/v8/V8CSSStyleRule.h" +#include "bindings/core/v8/V8CSSSupportsRule.h" +#include "bindings/core/v8/V8CSSViewportRule.h" +#include "bindings/core/v8/V8WebKitCSSFilterRule.h" namespace WebCore { @@ -52,7 +51,7 @@ v8::Handle<v8::Object> wrap(CSSRule* impl, v8::Handle<v8::Object> creationContex switch (impl->type()) { case CSSRule::UNKNOWN_RULE: // CSSUnknownRule.idl is explicitly excluded as it doesn't add anything - // over CSSRule.idl (see bindings/derived_sources.gyp: 'idl_files'). + // over CSSRule.idl (see core/core.gypi: 'core_idl_files'). // -> Use the base class wrapper here. return V8CSSRule::createWrapper(impl, creationContext, isolate); case CSSRule::STYLE_RULE: @@ -75,8 +74,6 @@ v8::Handle<v8::Object> wrap(CSSRule* impl, v8::Handle<v8::Object> creationContex return wrap(toCSSSupportsRule(impl), creationContext, isolate); case CSSRule::VIEWPORT_RULE: return wrap(toCSSViewportRule(impl), creationContext, isolate); - case CSSRule::WEBKIT_REGION_RULE: - return wrap(toCSSRegionRule(impl), creationContext, isolate); case CSSRule::WEBKIT_FILTER_RULE: return wrap(toCSSFilterRule(impl), creationContext, isolate); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp index 6d118a383c3..c7f3d7ab009 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp @@ -29,12 +29,12 @@ */ #include "config.h" -#include "V8CSSStyleDeclaration.h" +#include "bindings/core/v8/V8CSSStyleDeclaration.h" -#include "CSSPropertyNames.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "core/css/CSSParser.h" +#include "core/CSSPropertyNames.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSStyleDeclaration.h" #include "core/css/CSSValue.h" @@ -49,7 +49,6 @@ #include "wtf/text/StringConcatenate.h" using namespace WTF; -using namespace std; namespace WebCore { @@ -81,17 +80,51 @@ static bool hasCSSPropertyNamePrefix(const String& propertyName, const char* pre } struct CSSPropertyInfo { - unsigned propID: 30; // CSSPropertyID - unsigned nameWithDash: 1; - unsigned nameWithCssPrefix: 1; + CSSPropertyID propID; }; -static inline void countCssPropertyInfoUsage(const CSSPropertyInfo& propInfo) +static CSSPropertyID cssResolvedPropertyID(const String& propertyName) { - if (propInfo.nameWithDash) - UseCounter::count(activeDOMWindow(), UseCounter::CSSStyleDeclarationPropertyName); - if (propInfo.propID == CSSPropertyFloat && !propInfo.nameWithCssPrefix) - UseCounter::count(activeDOMWindow(), UseCounter::CSSStyleDeclarationFloatPropertyName); + unsigned length = propertyName.length(); + if (!length) + return CSSPropertyInvalid; + + StringBuilder builder; + builder.reserveCapacity(length); + + unsigned i = 0; + bool hasSeenDash = false; + + if (hasCSSPropertyNamePrefix(propertyName, "css")) + i += 3; + else if (hasCSSPropertyNamePrefix(propertyName, "webkit")) + builder.append('-'); + else if (isASCIIUpper(propertyName[0])) + return CSSPropertyInvalid; + + bool hasSeenUpper = isASCIIUpper(propertyName[i]); + + builder.append(toASCIILower(propertyName[i++])); + + for (; i < length; ++i) { + UChar c = propertyName[i]; + if (!isASCIIUpper(c)) { + if (c == '-') + hasSeenDash = true; + builder.append(c); + } else { + hasSeenUpper = true; + builder.append('-'); + builder.append(toASCIILower(c)); + } + } + + // Reject names containing both dashes and upper-case characters, such as "border-rightColor". + if (hasSeenDash && hasSeenUpper) + return CSSPropertyInvalid; + + String propName = builder.toString(); + return cssPropertyID(propName); } // When getting properties on CSSStyleDeclarations, the name used from @@ -110,52 +143,13 @@ static CSSPropertyInfo* cssPropertyInfo(v8::Handle<v8::String> v8PropertyName) DEFINE_STATIC_LOCAL(CSSPropertyInfoMap, map, ()); CSSPropertyInfo* propInfo = map.get(propertyName); if (!propInfo) { - unsigned length = propertyName.length(); - if (!length) - return 0; - - StringBuilder builder; - builder.reserveCapacity(length); - - unsigned i = 0; - bool hasSeenDash = false; - bool hasSeenCssPrefix = false; - - if (hasCSSPropertyNamePrefix(propertyName, "css")) { - hasSeenCssPrefix = true; - i += 3; - } else if (hasCSSPropertyNamePrefix(propertyName, "webkit")) { - builder.append('-'); - } else if (isASCIIUpper(propertyName[0])) { - return 0; - } - - builder.append(toASCIILower(propertyName[i++])); - - for (; i < length; ++i) { - UChar c = propertyName[i]; - if (!isASCIIUpper(c)) { - if (c == '-') - hasSeenDash = true; - builder.append(c); - } - else { - builder.append('-'); - builder.append(toASCIILower(c)); - } - } - - String propName = builder.toString(); - CSSPropertyID propertyID = cssPropertyID(propName); - if (propertyID && RuntimeCSSEnabled::isCSSPropertyEnabled(propertyID)) { - propInfo = new CSSPropertyInfo(); - propInfo->propID = propertyID; - propInfo->nameWithDash = hasSeenDash; - propInfo->nameWithCssPrefix = hasSeenCssPrefix; - map.add(propertyName, propInfo); - } + propInfo = new CSSPropertyInfo(); + propInfo->propID = cssResolvedPropertyID(propertyName); + map.add(propertyName, propInfo); } - return propInfo; + if (propInfo->propID && RuntimeCSSEnabled::isCSSPropertyEnabled(propInfo->propID)) + return propInfo; + return 0; } void V8CSSStyleDeclaration::namedPropertyEnumeratorCustom(const v8::PropertyCallbackInfo<v8::Array>& info) @@ -170,7 +164,7 @@ void V8CSSStyleDeclaration::namedPropertyEnumeratorCustom(const v8::PropertyCall if (RuntimeCSSEnabled::isCSSPropertyEnabled(propertyId)) propertyNames.append(getJSPropertyName(propertyId)); } - sort(propertyNames.begin(), propertyNames.end(), codePointCompareLessThan); + std::sort(propertyNames.begin(), propertyNames.end(), codePointCompareLessThan); propertyNamesLength = propertyNames.size(); } @@ -178,7 +172,7 @@ void V8CSSStyleDeclaration::namedPropertyEnumeratorCustom(const v8::PropertyCall for (unsigned i = 0; i < propertyNamesLength; ++i) { String key = propertyNames.at(i); ASSERT(!key.isNull()); - properties->Set(v8::Integer::New(i, info.GetIsolate()), v8String(info.GetIsolate(), key)); + properties->Set(v8::Integer::New(info.GetIsolate(), i), v8String(info.GetIsolate(), key)); } v8SetReturnValue(info, properties); @@ -188,8 +182,7 @@ void V8CSSStyleDeclaration::namedPropertyQueryCustom(v8::Local<v8::String> v8Nam { // NOTE: cssPropertyInfo lookups incur several mallocs. // Successful lookups have the same cost the first time, but are cached. - if (CSSPropertyInfo* propInfo = cssPropertyInfo(v8Name)) { - countCssPropertyInfoUsage(*propInfo); + if (cssPropertyInfo(v8Name)) { v8SetReturnValueInt(info, 0); return; } @@ -208,32 +201,27 @@ void V8CSSStyleDeclaration::namedPropertyGetterCustom(v8::Local<v8::String> name if (!propInfo) return; - countCssPropertyInfoUsage(*propInfo); - CSSStyleDeclaration* imp = V8CSSStyleDeclaration::toNative(info.Holder()); - RefPtr<CSSValue> cssValue = imp->getPropertyCSSValueInternal(static_cast<CSSPropertyID>(propInfo->propID)); + CSSStyleDeclaration* impl = V8CSSStyleDeclaration::toNative(info.Holder()); + RefPtrWillBeRawPtr<CSSValue> cssValue = impl->getPropertyCSSValueInternal(static_cast<CSSPropertyID>(propInfo->propID)); if (cssValue) { v8SetReturnValueStringOrNull(info, cssValue->cssText(), info.GetIsolate()); return; } - String result = imp->getPropertyValueInternal(static_cast<CSSPropertyID>(propInfo->propID)); - if (result.isNull()) - result = ""; // convert null to empty string. - + String result = impl->getPropertyValueInternal(static_cast<CSSPropertyID>(propInfo->propID)); v8SetReturnValueString(info, result, info.GetIsolate()); } void V8CSSStyleDeclaration::namedPropertySetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { - CSSStyleDeclaration* imp = V8CSSStyleDeclaration::toNative(info.Holder()); + CSSStyleDeclaration* impl = V8CSSStyleDeclaration::toNative(info.Holder()); CSSPropertyInfo* propInfo = cssPropertyInfo(name); if (!propInfo) return; - countCssPropertyInfoUsage(*propInfo); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, propertyValue, value); + TOSTRING_VOID(V8StringResource<WithNullCheck>, propertyValue, value); ExceptionState exceptionState(ExceptionState::SetterContext, getPropertyName(static_cast<CSSPropertyID>(propInfo->propID)), "CSSStyleDeclaration", info.Holder(), info.GetIsolate()); - imp->setPropertyInternal(static_cast<CSSPropertyID>(propInfo->propID), propertyValue, false, exceptionState); + impl->setPropertyInternal(static_cast<CSSPropertyID>(propInfo->propID), propertyValue, false, exceptionState); if (exceptionState.throwIfNeeded()) return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSValueCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSValueCustom.cpp index 3db5c35477c..44dc8e69ab8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSValueCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSValueCustom.cpp @@ -29,16 +29,12 @@ */ #include "config.h" -#include "V8CSSValue.h" +#include "bindings/core/v8/V8CSSValue.h" -#include "V8CSSPrimitiveValue.h" -#include "V8CSSValueList.h" -#include "V8SVGColor.h" -#include "V8SVGPaint.h" -#include "V8WebKitCSSFilterValue.h" -#include "V8WebKitCSSMixFunctionValue.h" -#include "V8WebKitCSSTransformValue.h" -#include "core/css/CSSMixFunctionValue.h" +#include "bindings/core/v8/V8CSSPrimitiveValue.h" +#include "bindings/core/v8/V8CSSValueList.h" +#include "bindings/core/v8/V8WebKitCSSFilterValue.h" +#include "bindings/core/v8/V8WebKitCSSTransformValue.h" namespace WebCore { @@ -47,18 +43,12 @@ v8::Handle<v8::Object> wrap(CSSValue* impl, v8::Handle<v8::Object> creationConte ASSERT(impl); if (impl->isTransformValue()) return wrap(toCSSTransformValue(impl), creationContext, isolate); - if (impl->isMixFunctionValue()) - return wrap(toCSSMixFunctionValue(impl), creationContext, isolate); if (impl->isFilterValue()) return wrap(toCSSFilterValue(impl), creationContext, isolate); if (impl->isValueList()) return wrap(toCSSValueList(impl), creationContext, isolate); if (impl->isPrimitiveValue()) return wrap(toCSSPrimitiveValue(impl), creationContext, isolate); - if (impl->isSVGPaint()) - return wrap(toSVGPaint(impl), creationContext, isolate); - if (impl->isSVGColor()) - return wrap(toSVGColor(impl), creationContext, isolate); return V8CSSValue::createWrapper(impl, creationContext, isolate); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp index 3e13d83e57e..d9d036df3cc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp @@ -29,14 +29,14 @@ */ #include "config.h" -#include "V8CanvasRenderingContext2D.h" +#include "bindings/core/v8/V8CanvasRenderingContext2D.h" -#include "V8CanvasGradient.h" -#include "V8CanvasPattern.h" -#include "V8HTMLCanvasElement.h" -#include "V8HTMLImageElement.h" -#include "V8HTMLVideoElement.h" -#include "V8ImageData.h" +#include "bindings/core/v8/V8CanvasGradient.h" +#include "bindings/core/v8/V8CanvasPattern.h" +#include "bindings/core/v8/V8HTMLCanvasElement.h" +#include "bindings/core/v8/V8HTMLImageElement.h" +#include "bindings/core/v8/V8HTMLVideoElement.h" +#include "bindings/core/v8/V8ImageData.h" #include "bindings/v8/V8Binding.h" #include "core/html/canvas/CanvasGradient.h" #include "core/html/canvas/CanvasPattern.h" @@ -59,13 +59,10 @@ static v8::Handle<v8::Value> toV8Object(CanvasStyle* style, v8::Handle<v8::Objec static PassRefPtr<CanvasStyle> toCanvasStyle(v8::Handle<v8::Value> value, v8::Isolate* isolate) { - if (V8CanvasGradient::hasInstance(value, isolate, worldType(isolate))) - return CanvasStyle::createFromGradient(V8CanvasGradient::toNative(v8::Handle<v8::Object>::Cast(value))); - - if (V8CanvasPattern::hasInstance(value, isolate, worldType(isolate))) - return CanvasStyle::createFromPattern(V8CanvasPattern::toNative(v8::Handle<v8::Object>::Cast(value))); - - return 0; + RefPtr<CanvasStyle> canvasStyle = CanvasStyle::createFromGradient(V8CanvasGradient::toNativeWithTypeCheck(isolate, value)); + if (canvasStyle) + return canvasStyle; + return CanvasStyle::createFromPattern(V8CanvasPattern::toNativeWithTypeCheck(isolate, value)); } void V8CanvasRenderingContext2D::strokeStyleAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) @@ -77,10 +74,12 @@ void V8CanvasRenderingContext2D::strokeStyleAttributeGetterCustom(const v8::Prop void V8CanvasRenderingContext2D::strokeStyleAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { CanvasRenderingContext2D* impl = V8CanvasRenderingContext2D::toNative(info.Holder()); - if (value->IsString()) - impl->setStrokeColor(toCoreString(value.As<v8::String>())); - else - impl->setStrokeStyle(toCanvasStyle(value, info.GetIsolate())); + if (RefPtr<CanvasStyle> canvasStyle = toCanvasStyle(value, info.GetIsolate())) { + impl->setStrokeStyle(canvasStyle); + } else { + TOSTRING_VOID(V8StringResource<>, colorString, value); + impl->setStrokeColor(colorString); + } } void V8CanvasRenderingContext2D::fillStyleAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) @@ -92,10 +91,12 @@ void V8CanvasRenderingContext2D::fillStyleAttributeGetterCustom(const v8::Proper void V8CanvasRenderingContext2D::fillStyleAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { CanvasRenderingContext2D* impl = V8CanvasRenderingContext2D::toNative(info.Holder()); - if (value->IsString()) - impl->setFillColor(toCoreString(value.As<v8::String>())); - else - impl->setFillStyle(toCanvasStyle(value, info.GetIsolate())); + if (RefPtr<CanvasStyle> canvasStyle = toCanvasStyle(value, info.GetIsolate())) { + impl->setFillStyle(canvasStyle); + } else { + TOSTRING_VOID(V8StringResource<>, colorString, value); + impl->setFillColor(colorString); + } } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContextCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContextCustom.cpp deleted file mode 100644 index 66a73c48541..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContextCustom.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007-2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8CanvasRenderingContext.h" - -#include "V8CanvasRenderingContext2D.h" -#include "V8WebGLRenderingContext.h" -#include "core/html/canvas/CanvasRenderingContext.h" - -namespace WebCore { - -v8::Handle<v8::Object> wrap(CanvasRenderingContext* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(impl); - if (impl->is2d()) - return wrap(toCanvasRenderingContext2D(impl), creationContext, isolate); - if (impl->is3d()) - return wrap(toWebGLRenderingContext(impl), creationContext, isolate); - ASSERT_NOT_REACHED(); - return v8::Handle<v8::Object>(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ClientCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ClientCustom.cpp new file mode 100644 index 00000000000..b7975759511 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ClientCustom.cpp @@ -0,0 +1,39 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/modules/v8/V8Client.h" + +#include "bindings/v8/ExceptionMessages.h" +#include "bindings/v8/ExceptionState.h" +#include "bindings/v8/SerializedScriptValue.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/MessagePort.h" +#include "modules/serviceworkers/ServiceWorker.h" +#include "wtf/ArrayBuffer.h" + +namespace WebCore { + +void V8Client::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "ServiceWorker", info.Holder(), info.GetIsolate()); + Client* client = V8Client::toNative(info.Holder()); + MessagePortArray ports; + ArrayBufferArray arrayBuffers; + if (info.Length() > 1) { + const int transferablesArgIndex = 1; + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, ports, arrayBuffers, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); + return; + } + } + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) + return; + ExecutionContext* context = currentExecutionContext(info.GetIsolate()); + client->postMessage(context, message.release(), &ports, exceptionState); + exceptionState.throwIfNeeded(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CryptoCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CryptoCustom.cpp index d183e31f9f5..d69042811c2 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CryptoCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CryptoCustom.cpp @@ -23,12 +23,11 @@ */ #include "config.h" -#include "V8Crypto.h" +#include "bindings/modules/v8/V8Crypto.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "core/dom/ExceptionCode.h" #include "modules/crypto/Crypto.h" @@ -36,9 +35,6 @@ namespace WebCore { -// This custom binding is shared by V8WorkerCrypto. As such: -// * Do not call V8Crypto::toNative() -// * Must be threadsafe void V8Crypto::getRandomValuesMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ExecutionContext, "getRandomValues", "Crypto", info.Holder(), info.GetIsolate()); @@ -49,13 +45,14 @@ void V8Crypto::getRandomValuesMethodCustom(const v8::FunctionCallbackInfo<v8::Va } v8::Handle<v8::Value> buffer = info[0]; - if (!V8ArrayBufferView::hasInstance(buffer, info.GetIsolate(), worldType(info.GetIsolate()))) { + if (!V8ArrayBufferView::hasInstance(buffer, info.GetIsolate())) { exceptionState.throwTypeError("First argument is not an ArrayBufferView"); } else { ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(buffer)); ASSERT(arrayBufferView); - Crypto::getRandomValues(arrayBufferView, exceptionState); + Crypto* crypto = V8Crypto::toNative(info.Holder()); + crypto->getRandomValues(arrayBufferView, exceptionState); } if (exceptionState.throwIfNeeded()) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomEventCustom.cpp index 143f0cac326..f0ef6e4d600 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomEventCustom.cpp @@ -29,23 +29,22 @@ */ #include "config.h" -#include "V8CustomEvent.h" +#include "bindings/core/v8/V8CustomEvent.h" -#include "RuntimeEnabledFeatures.h" -#include "V8Event.h" +#include "bindings/core/v8/V8Event.h" #include "bindings/v8/Dictionary.h" -#include "bindings/v8/ScriptState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/ContextFeatures.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { static v8::Handle<v8::Value> cacheState(v8::Handle<v8::Object> customEvent, v8::Handle<v8::Value> detail, v8::Isolate* isolate) { - customEvent->SetHiddenValue(V8HiddenPropertyName::detail(isolate), detail); + V8HiddenValue::setHiddenValue(isolate, customEvent, V8HiddenValue::detail(isolate), detail); return detail; } @@ -54,7 +53,7 @@ void V8CustomEvent::detailAttributeGetterCustom(const v8::PropertyCallbackInfo<v { CustomEvent* event = V8CustomEvent::toNative(info.Holder()); - v8::Handle<v8::Value> result = info.Holder()->GetHiddenValue(V8HiddenPropertyName::detail(info.GetIsolate())); + v8::Handle<v8::Value> result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::detail(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, result); @@ -64,7 +63,7 @@ void V8CustomEvent::detailAttributeGetterCustom(const v8::PropertyCallbackInfo<v if (!event->serializedDetail()) { // If we're in an isolated world and the event was created in the main world, // we need to find the 'detail' property on the main world wrapper and clone it. - v8::Local<v8::Value> mainWorldDetail = getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenPropertyName::detail(info.GetIsolate())); + v8::Local<v8::Value> mainWorldDetail = V8HiddenValue::getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenValue::detail(info.GetIsolate())); if (!mainWorldDetail.IsEmpty()) event->setSerializedDetail(SerializedScriptValue::createAndSwallowExceptions(mainWorldDetail, info.GetIsolate())); } @@ -83,16 +82,16 @@ void V8CustomEvent::initCustomEventMethodCustom(const v8::FunctionCallbackInfo<v CustomEvent* event = V8CustomEvent::toNative(info.Holder()); ASSERT(!event->serializedDetail()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, typeArg, info[0]); - V8TRYCATCH_VOID(bool, canBubbleArg, info[1]->BooleanValue()); - V8TRYCATCH_VOID(bool, cancelableArg, info[2]->BooleanValue()); + TOSTRING_VOID(V8StringResource<>, typeArg, info[0]); + TONATIVE_VOID(bool, canBubbleArg, info[1]->BooleanValue()); + TONATIVE_VOID(bool, cancelableArg, info[2]->BooleanValue()); v8::Handle<v8::Value> detailsArg = info[3]; event->initEvent(typeArg, canBubbleArg, cancelableArg); if (!detailsArg.IsEmpty()) { - info.Holder()->SetHiddenValue(V8HiddenPropertyName::detail(info.GetIsolate()), detailsArg); - if (isolatedWorldForIsolate(info.GetIsolate())) + V8HiddenValue::setHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::detail(info.GetIsolate()), detailsArg); + if (DOMWrapperWorld::current(info.GetIsolate()).isIsolatedWorld()) event->setSerializedDetail(SerializedScriptValue::createAndSwallowExceptions(detailsArg, info.GetIsolate())); } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp index fc597c11034..0f411122352 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8SQLStatementErrorCallback.h" -#include "V8SQLError.h" -#include "V8SQLTransaction.h" +#include "bindings/modules/v8/V8SQLError.h" +#include "bindings/modules/v8/V8SQLStatementErrorCallback.h" +#include "bindings/modules/v8/V8SQLTransaction.h" #include "bindings/v8/ScriptController.h" #include "core/dom/ExecutionContext.h" #include "wtf/Assertions.h" @@ -44,23 +44,22 @@ bool V8SQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLEr if (!canInvokeCallback()) return true; - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - - v8::Handle<v8::Context> v8Context = toV8Context(executionContext(), m_world.get()); - if (v8Context.IsEmpty()) + v8::Isolate* isolate = m_scriptState->isolate(); + if (m_scriptState->contextIsEmpty()) return true; - v8::Context::Scope scope(v8Context); + ScriptState::Scope scope(m_scriptState.get()); - v8::Handle<v8::Value> transactionHandle = toV8(transaction, v8::Handle<v8::Object>(), v8Context->GetIsolate()); - v8::Handle<v8::Value> errorHandle = toV8(error, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> transactionHandle = toV8(transaction, m_scriptState->context()->Global(), isolate); + v8::Handle<v8::Value> errorHandle = toV8(error, m_scriptState->context()->Global(), isolate); if (transactionHandle.IsEmpty() || errorHandle.IsEmpty()) { if (!isScriptControllerTerminating()) CRASH(); return true; } + ASSERT(transactionHandle->IsObject()); + v8::Handle<v8::Value> argv[] = { transactionHandle, errorHandle @@ -69,7 +68,7 @@ bool V8SQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLEr v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); - v8::Handle<v8::Value> result = ScriptController::callFunction(executionContext(), m_callback.newLocal(isolate), isolate->GetCurrentContext()->Global(), 2, argv, isolate); + v8::Handle<v8::Value> result = ScriptController::callFunction(executionContext(), m_callback.newLocal(isolate), m_scriptState->context()->Global(), WTF_ARRAY_LENGTH(argv), argv, isolate); // FIXME: This comment doesn't make much sense given what the code is actually doing. // diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp index f2c4d730d24..6331ef1bf99 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp @@ -32,20 +32,19 @@ #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "core/dom/ExecutionContext.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/FrameConsole.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" #include "core/inspector/ScriptCallStack.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" -#include "core/page/Page.h" -#include "core/page/PageConsole.h" #include "wtf/text/WTFString.h" namespace WebCore { -PassRefPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(v8::Handle<v8::Object> resolver, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(v8::Handle<v8::Object> resolver, v8::Isolate* isolate) { - return adoptRef(new V8CustomXPathNSResolver(resolver, isolate)); + return adoptRefWillBeNoop(new V8CustomXPathNSResolver(resolver, isolate)); } V8CustomXPathNSResolver::V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver, v8::Isolate* isolate) @@ -71,9 +70,9 @@ AtomicString V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) } if (lookupNamespaceURIFunc.IsEmpty() && !m_resolver->IsFunction()) { - Frame* frame = activeDOMWindow()->frame(); - if (frame && frame->page()) - frame->page()->console().addMessage(JSMessageSource, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method."); + LocalFrame* frame = callingDOMWindow(m_isolate)->frame(); + if (frame && frame->host()) + frame->console().addMessage(JSMessageSource, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method."); return nullAtom; } @@ -85,14 +84,19 @@ AtomicString V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) v8::Handle<v8::Value> argv[argc] = { v8String(m_isolate, prefix) }; v8::Handle<v8::Function> function = lookupNamespaceURIFunc.IsEmpty() ? v8::Handle<v8::Function>::Cast(m_resolver) : lookupNamespaceURIFunc; - v8::Handle<v8::Value> retval = ScriptController::callFunction(activeExecutionContext(), function, m_resolver, argc, argv, m_isolate); + v8::Handle<v8::Value> retval = ScriptController::callFunction(callingExecutionContext(m_isolate), function, m_resolver, argc, argv, m_isolate); // Eat exceptions from namespace resolver and return an empty string. This will most likely cause NamespaceError. if (tryCatch.HasCaught()) return nullAtom; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, returnString, retval, nullAtom); + TOSTRING_DEFAULT(V8StringResource<WithNullCheck>, returnString, retval, nullAtom); return returnString; } +void V8CustomXPathNSResolver::trace(Visitor* visitor) +{ + XPathNSResolver::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.h index aa3e01a243d..4c6712bb9f3 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.h @@ -42,13 +42,15 @@ namespace WebCore { // V8CustomXPathNSResolver does not create a persistent handle to the // given resolver object. So the lifetime of V8CustomXPathNSResolver // must not exceed the lifetime of the passed handle. -class V8CustomXPathNSResolver : public XPathNSResolver { +class V8CustomXPathNSResolver FINAL : public XPathNSResolver { public: - static PassRefPtr<V8CustomXPathNSResolver> create(v8::Handle<v8::Object> resolver, v8::Isolate*); + static PassRefPtrWillBeRawPtr<V8CustomXPathNSResolver> create(v8::Handle<v8::Object> resolver, v8::Isolate*); virtual ~V8CustomXPathNSResolver(); virtual AtomicString lookupNamespaceURI(const String& prefix) OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + private: V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver, v8::Isolate*); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.cpp index 73efbd69ad4..3d7572ca3ca 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.cpp @@ -35,7 +35,7 @@ namespace WebCore { static void initializeScriptWrappableForInterface(DataView* object) { if (ScriptWrappable::wrapperCanBeStoredInObject(object)) - ScriptWrappable::setTypeInfoInObject(object, &V8DataView::wrapperTypeInfo); + ScriptWrappable::fromObject(object)->setTypeInfo(&V8DataView::wrapperTypeInfo); else ASSERT_NOT_REACHED(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.h index 502c010fe46..6459cbdd6e2 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<DataView> V8DataView; -template<> -class WrapperTypeTraits<DataView> : public TypedArrayWrapperTraits<DataView> { }; - - inline v8::Handle<v8::Object> wrap(DataView* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<DataView>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DedicatedWorkerGlobalScopeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DedicatedWorkerGlobalScopeCustom.cpp index a356f03e4fe..b95c50747e7 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DedicatedWorkerGlobalScopeCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DedicatedWorkerGlobalScopeCustom.cpp @@ -29,13 +29,12 @@ */ #include "config.h" -#include "V8DedicatedWorkerGlobalScope.h" +#include "bindings/core/v8/V8DedicatedWorkerGlobalScope.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/V8WorkerGlobalScopeEventListener.h" #include "core/workers/DedicatedWorkerGlobalScope.h" #include "wtf/ArrayBuffer.h" @@ -44,23 +43,21 @@ namespace WebCore { void V8DedicatedWorkerGlobalScope::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "WorkerGlobalScope", info.Holder(), info.GetIsolate()); DedicatedWorkerGlobalScope* workerGlobalScope = V8DedicatedWorkerGlobalScope::toNative(info.Holder()); MessagePortArray ports; ArrayBufferArray arrayBuffers; if (info.Length() > 1) { const int transferablesArgIndex = 1; - bool notASequence = false; - if (!extractTransferables(info[transferablesArgIndex], ports, arrayBuffers, notASequence, info.GetIsolate())) { - if (notASequence) - throwTypeError(ExceptionMessages::failedToExecute("postMessage", "WorkerGlobalScope", ExceptionMessages::notAnArrayTypeArgumentOrValue(transferablesArgIndex + 1)), info.GetIsolate()); + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, ports, arrayBuffers, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); return; } } - bool didThrow = false; - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, didThrow, info.GetIsolate()); - if (didThrow) + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); + workerGlobalScope->postMessage(message.release(), &ports, exceptionState); exceptionState.throwIfNeeded(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceMotionEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceMotionEventCustom.cpp index a170e1cde5f..ecf0ca7e9ee 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceMotionEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceMotionEventCustom.cpp @@ -24,7 +24,7 @@ */ #include "config.h" -#include "V8DeviceMotionEvent.h" +#include "bindings/modules/v8/V8DeviceMotionEvent.h" #include "bindings/v8/V8Binding.h" #include "modules/device_orientation/DeviceMotionData.h" @@ -34,66 +34,66 @@ namespace WebCore { namespace { -RefPtr<DeviceMotionData::Acceleration> readAccelerationArgument(v8::Local<v8::Value> value, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<DeviceMotionData::Acceleration> readAccelerationArgument(v8::Local<v8::Value> value, v8::Isolate* isolate) { if (isUndefinedOrNull(value)) - return 0; + return nullptr; // Given the test above, this will always yield an object. v8::Local<v8::Object> object = value->ToObject(); v8::Local<v8::Value> xValue = object->Get(v8AtomicString(isolate, "x")); if (xValue.IsEmpty()) - return 0; + return nullptr; bool canProvideX = !isUndefinedOrNull(xValue); double x = xValue->NumberValue(); v8::Local<v8::Value> yValue = object->Get(v8AtomicString(isolate, "y")); if (yValue.IsEmpty()) - return 0; + return nullptr; bool canProvideY = !isUndefinedOrNull(yValue); double y = yValue->NumberValue(); v8::Local<v8::Value> zValue = object->Get(v8AtomicString(isolate, "z")); if (zValue.IsEmpty()) - return 0; + return nullptr; bool canProvideZ = !isUndefinedOrNull(zValue); double z = zValue->NumberValue(); if (!canProvideX && !canProvideY && !canProvideZ) - return 0; + return nullptr; return DeviceMotionData::Acceleration::create(canProvideX, x, canProvideY, y, canProvideZ, z); } -RefPtr<DeviceMotionData::RotationRate> readRotationRateArgument(v8::Local<v8::Value> value, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<DeviceMotionData::RotationRate> readRotationRateArgument(v8::Local<v8::Value> value, v8::Isolate* isolate) { if (isUndefinedOrNull(value)) - return 0; + return nullptr; // Given the test above, this will always yield an object. v8::Local<v8::Object> object = value->ToObject(); v8::Local<v8::Value> alphaValue = object->Get(v8AtomicString(isolate, "alpha")); if (alphaValue.IsEmpty()) - return 0; + return nullptr; bool canProvideAlpha = !isUndefinedOrNull(alphaValue); double alpha = alphaValue->NumberValue(); v8::Local<v8::Value> betaValue = object->Get(v8AtomicString(isolate, "beta")); if (betaValue.IsEmpty()) - return 0; + return nullptr; bool canProvideBeta = !isUndefinedOrNull(betaValue); double beta = betaValue->NumberValue(); v8::Local<v8::Value> gammaValue = object->Get(v8AtomicString(isolate, "gamma")); if (gammaValue.IsEmpty()) - return 0; + return nullptr; bool canProvideGamma = !isUndefinedOrNull(gammaValue); double gamma = gammaValue->NumberValue(); if (!canProvideAlpha && !canProvideBeta && !canProvideGamma) - return 0; + return nullptr; return DeviceMotionData::RotationRate::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma); } @@ -102,18 +102,18 @@ RefPtr<DeviceMotionData::RotationRate> readRotationRateArgument(v8::Local<v8::Va void V8DeviceMotionEvent::initDeviceMotionEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - DeviceMotionEvent* imp = V8DeviceMotionEvent::toNative(info.Holder()); + DeviceMotionEvent* impl = V8DeviceMotionEvent::toNative(info.Holder()); v8::Isolate* isolate = info.GetIsolate(); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]); + TOSTRING_VOID(V8StringResource<>, type, info[0]); bool bubbles = info[1]->BooleanValue(); bool cancelable = info[2]->BooleanValue(); - RefPtr<DeviceMotionData::Acceleration> acceleration = readAccelerationArgument(info[3], isolate); - RefPtr<DeviceMotionData::Acceleration> accelerationIncludingGravity = readAccelerationArgument(info[4], isolate); - RefPtr<DeviceMotionData::RotationRate> rotationRate = readRotationRateArgument(info[5], isolate); + RefPtrWillBeRawPtr<DeviceMotionData::Acceleration> acceleration = readAccelerationArgument(info[3], isolate); + RefPtrWillBeRawPtr<DeviceMotionData::Acceleration> accelerationIncludingGravity = readAccelerationArgument(info[4], isolate); + RefPtrWillBeRawPtr<DeviceMotionData::RotationRate> rotationRate = readRotationRateArgument(info[5], isolate); bool intervalProvided = !isUndefinedOrNull(info[6]); double interval = info[6]->NumberValue(); - RefPtr<DeviceMotionData> deviceMotionData = DeviceMotionData::create(acceleration, accelerationIncludingGravity, rotationRate, intervalProvided, interval); - imp->initDeviceMotionEvent(type, bubbles, cancelable, deviceMotionData.get()); + RefPtrWillBeRawPtr<DeviceMotionData> deviceMotionData = DeviceMotionData::create(acceleration.release(), accelerationIncludingGravity.release(), rotationRate.release(), intervalProvided, interval); + impl->initDeviceMotionEvent(type, bubbles, cancelable, deviceMotionData.get()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp index ef2a0a92e48..c9d68ec2057 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp @@ -24,7 +24,7 @@ */ #include "config.h" -#include "V8DeviceOrientationEvent.h" +#include "bindings/modules/v8/V8DeviceOrientationEvent.h" #include "bindings/v8/V8Binding.h" #include "modules/device_orientation/DeviceOrientationData.h" @@ -34,8 +34,8 @@ namespace WebCore { void V8DeviceOrientationEvent::initDeviceOrientationEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - DeviceOrientationEvent* imp = V8DeviceOrientationEvent::toNative(info.Holder()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]); + DeviceOrientationEvent* impl = V8DeviceOrientationEvent::toNative(info.Holder()); + TOSTRING_VOID(V8StringResource<>, type, info[0]); bool bubbles = info[1]->BooleanValue(); bool cancelable = info[2]->BooleanValue(); // If alpha, beta, gamma or absolute are null or undefined, mark them as not provided. @@ -48,8 +48,8 @@ void V8DeviceOrientationEvent::initDeviceOrientationEventMethodCustom(const v8:: double gamma = info[5]->NumberValue(); bool absoluteProvided = !isUndefinedOrNull(info[6]); bool absolute = info[6]->BooleanValue(); - RefPtr<DeviceOrientationData> orientation = DeviceOrientationData::create(alphaProvided, alpha, betaProvided, beta, gammaProvided, gamma, absoluteProvided, absolute); - imp->initDeviceOrientationEvent(type, bubbles, cancelable, orientation.get()); + RefPtrWillBeRawPtr<DeviceOrientationData> orientation = DeviceOrientationData::create(alphaProvided, alpha, betaProvided, beta, gammaProvided, gamma, absoluteProvided, absolute); + impl->initDeviceOrientationEvent(type, bubbles, cancelable, orientation.get()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DocumentCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DocumentCustom.cpp index 94ed248cb90..930ba77f07d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DocumentCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DocumentCustom.cpp @@ -29,16 +29,16 @@ */ #include "config.h" -#include "V8Document.h" +#include "bindings/core/v8/V8Document.h" -#include "V8CanvasRenderingContext2D.h" -#include "V8DOMImplementation.h" -#include "V8Node.h" -#include "V8Touch.h" -#include "V8TouchList.h" -#include "V8WebGLRenderingContext.h" -#include "V8XPathNSResolver.h" -#include "V8XPathResult.h" +#include "bindings/core/v8/V8CanvasRenderingContext2D.h" +#include "bindings/core/v8/V8DOMImplementation.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8Touch.h" +#include "bindings/core/v8/V8TouchList.h" +#include "bindings/core/v8/V8WebGLRenderingContext.h" +#include "bindings/core/v8/V8XPathNSResolver.h" +#include "bindings/core/v8/V8XPathResult.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ScriptController.h" @@ -49,8 +49,8 @@ #include "core/dom/ExceptionCode.h" #include "core/dom/Node.h" #include "core/dom/TouchList.h" +#include "core/frame/LocalFrame.h" #include "core/html/canvas/CanvasRenderingContext.h" -#include "core/frame/Frame.h" #include "core/xml/DocumentXPathEvaluator.h" #include "core/xml/XPathNSResolver.h" #include "core/xml/XPathResult.h" @@ -60,27 +60,23 @@ namespace WebCore { void V8Document::evaluateMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - RefPtr<Document> document = V8Document::toNative(info.Holder()); + RefPtrWillBeRawPtr<Document> document = V8Document::toNative(info.Holder()); + ASSERT(document); ExceptionState exceptionState(ExceptionState::ExecutionContext, "evaluate", "Document", info.Holder(), info.GetIsolate()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, expression, info[0]); - RefPtr<Node> contextNode; - if (V8Node::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate()))) - contextNode = V8Node::toNative(v8::Handle<v8::Object>::Cast(info[1])); + TOSTRING_VOID(V8StringResource<>, expression, info[0]); + RefPtrWillBeRawPtr<Node> contextNode = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[1]); const int resolverArgumentIndex = 2; - RefPtr<XPathNSResolver> resolver = toXPathNSResolver(info[resolverArgumentIndex], info.GetIsolate()); + RefPtrWillBeRawPtr<XPathNSResolver> resolver = toXPathNSResolver(info[resolverArgumentIndex], info.GetIsolate()); if (!resolver && !isUndefinedOrNull(info[resolverArgumentIndex])) { - exceptionState.throwTypeError(ExceptionMessages::incorrectArgumentType(resolverArgumentIndex + 1, "is not a resolver function.")); + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(resolverArgumentIndex + 1, "XPathNSResolver")); exceptionState.throwIfNeeded(); return; } int type = toInt32(info[3]); - RefPtr<XPathResult> inResult; - if (V8XPathResult::hasInstance(info[4], info.GetIsolate(), worldType(info.GetIsolate()))) - inResult = V8XPathResult::toNative(v8::Handle<v8::Object>::Cast(info[4])); - - V8TRYCATCH_VOID(RefPtr<XPathResult>, result, DocumentXPathEvaluator::evaluate(document.get(), expression, contextNode.get(), resolver.release(), type, inResult.get(), exceptionState)); + RefPtrWillBeRawPtr<XPathResult> inResult = V8XPathResult::toNativeWithTypeCheck(info.GetIsolate(), info[4]); + TONATIVE_VOID(RefPtrWillBeRawPtr<XPathResult>, result, DocumentXPathEvaluator::evaluate(*document, expression, contextNode.get(), resolver.release(), type, inResult.get(), exceptionState)); if (exceptionState.throwIfNeeded()) return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ElementCustom.cpp new file mode 100644 index 00000000000..0083ac9b055 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ElementCustom.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "bindings/core/v8/V8Element.h" + +#include "bindings/core/v8/V8AnimationEffect.h" +#include "bindings/core/v8/V8AnimationPlayer.h" +#include "bindings/v8/Dictionary.h" +#include "bindings/v8/ExceptionState.h" +#include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8BindingMacros.h" +#include "core/animation/ElementAnimation.h" +#include "core/dom/Element.h" +#include "core/frame/UseCounter.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "wtf/GetPtr.h" + +namespace WebCore { + +void V8Element::scrollLeftAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) +{ + ExceptionState exceptionState(ExceptionState::SetterContext, "scrollLeft", "Element", info.Holder(), info.GetIsolate()); + Element* impl = V8Element::toNative(info.Holder()); + + if (RuntimeEnabledFeatures::cssomSmoothScrollEnabled() && value->IsObject()) { + TONATIVE_VOID(Dictionary, scrollOptionsHorizontal, Dictionary(value, info.GetIsolate())); + impl->setScrollLeft(scrollOptionsHorizontal, exceptionState); + exceptionState.throwIfNeeded(); + return; + } + + TONATIVE_VOID_EXCEPTIONSTATE(float, position, toInt32(value, exceptionState), exceptionState); + impl->setScrollLeft(position); +} + +void V8Element::scrollTopAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) +{ + ExceptionState exceptionState(ExceptionState::SetterContext, "scrollTop", "Element", info.Holder(), info.GetIsolate()); + Element* impl = V8Element::toNative(info.Holder()); + + if (RuntimeEnabledFeatures::cssomSmoothScrollEnabled() && value->IsObject()) { + TONATIVE_VOID(Dictionary, scrollOptionsVertical, Dictionary(value, info.GetIsolate())); + impl->setScrollTop(scrollOptionsVertical, exceptionState); + exceptionState.throwIfNeeded(); + return; + } + + TONATIVE_VOID_EXCEPTIONSTATE(float, position, toInt32(value, exceptionState), exceptionState); + impl->setScrollTop(position); +} + +//////////////////////////////////////////////////////////////////////////////// +// Overload resolution for animate() +// FIXME: needs support for union types http://crbug.com/240176 +//////////////////////////////////////////////////////////////////////////////// + +// AnimationPlayer animate(AnimationEffect? effect); +void animate1Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(AnimationEffect*, effect, V8AnimationEffect::toNativeWithTypeCheck(info.GetIsolate(), info[0])); + v8SetReturnValueFast(info, WTF::getPtr(ElementAnimation::animate(*impl, effect)), impl); +} + +// [RaisesException] AnimationPlayer animate(sequence<Dictionary> effect); +void animate2Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "animate", "Element", info.Holder(), info.GetIsolate()); + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(Vector<Dictionary>, keyframes, toNativeArray<Dictionary>(info[0], 1, info.GetIsolate())); + RefPtr<AnimationPlayer> result = ElementAnimation::animate(*impl, keyframes, exceptionState); + if (exceptionState.throwIfNeeded()) + return; + v8SetReturnValueFast(info, WTF::getPtr(result.release()), impl); +} + +// AnimationPlayer animate(AnimationEffect? effect, double timing); +void animate3Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(AnimationEffect*, effect, V8AnimationEffect::toNativeWithTypeCheck(info.GetIsolate(), info[0])); + TONATIVE_VOID(double, duration, static_cast<double>(info[1]->NumberValue())); + v8SetReturnValueFast(info, WTF::getPtr(ElementAnimation::animate(*impl, effect, duration)), impl); +} + +// AnimationPlayer animate(AnimationEffect? effect, Dictionary timing); +void animate4Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(AnimationEffect*, effect, V8AnimationEffect::toNativeWithTypeCheck(info.GetIsolate(), info[0])); + TONATIVE_VOID(Dictionary, timingInput, Dictionary(info[1], info.GetIsolate())); + if (!timingInput.isUndefinedOrNull() && !timingInput.isObject()) { + throwTypeError(ExceptionMessages::failedToExecute("animate", "Element", "parameter 2 ('timingInput') is not an object."), info.GetIsolate()); + return; + } + v8SetReturnValueFast(info, WTF::getPtr(ElementAnimation::animate(*impl, effect, timingInput)), impl); +} + +// [RaisesException] AnimationPlayer animate(sequence<Dictionary> effect, double timing); +void animate5Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "animate", "Element", info.Holder(), info.GetIsolate()); + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(Vector<Dictionary>, keyframes, toNativeArray<Dictionary>(info[0], 1, info.GetIsolate())); + TONATIVE_VOID(double, duration, static_cast<double>(info[1]->NumberValue())); + RefPtr<AnimationPlayer> result = ElementAnimation::animate(*impl, keyframes, duration, exceptionState); + if (exceptionState.throwIfNeeded()) + return; + v8SetReturnValueFast(info, WTF::getPtr(result.release()), impl); +} + +// [RaisesException] AnimationPlayer animate(sequence<Dictionary> effect, Dictionary timing); +void animate6Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "animate", "Element", info.Holder(), info.GetIsolate()); + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(Vector<Dictionary>, keyframes, toNativeArray<Dictionary>(info[0], 1, info.GetIsolate())); + TONATIVE_VOID(Dictionary, timingInput, Dictionary(info[1], info.GetIsolate())); + if (!timingInput.isUndefinedOrNull() && !timingInput.isObject()) { + exceptionState.throwTypeError("parameter 2 ('timingInput') is not an object."); + exceptionState.throwIfNeeded(); + return; + } + RefPtr<AnimationPlayer> result = ElementAnimation::animate(*impl, keyframes, timingInput, exceptionState); + if (exceptionState.throwIfNeeded()) + return; + v8SetReturnValueFast(info, WTF::getPtr(result.release()), impl); +} + +void V8Element::animateMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + v8::Isolate* isolate = info.GetIsolate(); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "animate", "Element", info.Holder(), isolate); + // AnimationPlayer animate( + // (AnimationEffect or sequence<Dictionary>)? effect, + // optional (double or Dictionary) timing); + switch (info.Length()) { + case 1: + // null resolved as to AnimationEffect, as if the member were nullable: + // (AnimationEffect? or sequence<Dictionary>) + // instead of the *union* being nullable: + // (AnimationEffect or sequence<Dictionary>)? + // AnimationPlayer animate(AnimationEffect? effect); + if (info[0]->IsNull()) { + animate1Method(info); + return; + } + // AnimationPlayer animate(AnimationEffect effect); + if (V8AnimationEffect::hasInstance(info[0], isolate)) { + animate1Method(info); + return; + } + // [MeasureAs=ElementAnimateKeyframeListEffectNoTiming] + // AnimationPlayer animate(sequence<Dictionary> effect); + if (info[0]->IsArray()) { + UseCounter::count(callingExecutionContext(isolate), UseCounter::ElementAnimateKeyframeListEffectNoTiming); + animate2Method(info); + return; + } + break; + case 2: + // As above, null resolved to AnimationEffect + // AnimationPlayer animate(AnimationEffect? effect, Dictionary timing); + if (info[0]->IsNull() && info[1]->IsObject()) { + animate4Method(info); + return; + } + // AnimationPlayer animate(AnimationEffect? effect, double timing); + if (info[0]->IsNull()) { + animate3Method(info); + return; + } + // AnimationPlayer animate(AnimationEffect effect, Dictionary timing); + if (V8AnimationEffect::hasInstance(info[0], isolate) + && info[1]->IsObject()) { + animate4Method(info); + return; + } + // AnimationPlayer animate(AnimationEffect effect, double timing); + if (V8AnimationEffect::hasInstance(info[0], isolate)) { + animate3Method(info); + return; + } + // [MeasureAs=ElementAnimateKeyframeListEffectObjectTiming] + // AnimationPlayer animate(sequence<Dictionary> effect, Dictionary timing); + if (info[0]->IsArray() && info[1]->IsObject()) { + UseCounter::count(callingExecutionContext(isolate), UseCounter::ElementAnimateKeyframeListEffectObjectTiming); + animate6Method(info); + return; + } + // [MeasureAs=ElementAnimateKeyframeListEffectDoubleTiming] + // AnimationPlayer animate(sequence<Dictionary> effect, double timing); + if (info[0]->IsArray()) { + UseCounter::count(callingExecutionContext(isolate), UseCounter::ElementAnimateKeyframeListEffectDoubleTiming); + animate5Method(info); + return; + } + break; + default: + throwArityTypeError(exceptionState, "[1]", info.Length()); + return; + break; + } + exceptionState.throwTypeError("No function was found that matched the signature provided."); + exceptionState.throwIfNeeded(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntryCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntryCustom.cpp index 98fc46d1cbf..e74cf314240 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntryCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntryCustom.cpp @@ -29,11 +29,11 @@ */ #include "config.h" -#include "V8Entry.h" +#include "bindings/modules/v8/V8Entry.h" -#include "V8Attr.h" -#include "V8DirectoryEntry.h" -#include "V8FileEntry.h" +#include "bindings/core/v8/V8Attr.h" +#include "bindings/modules/v8/V8DirectoryEntry.h" +#include "bindings/modules/v8/V8FileEntry.h" #include "bindings/v8/V8Binding.h" #include "wtf/RefPtr.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntrySyncCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntrySyncCustom.cpp index 2ebd101e94f..b079b7699ad 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntrySyncCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntrySyncCustom.cpp @@ -29,11 +29,11 @@ */ #include "config.h" -#include "V8EntrySync.h" +#include "bindings/modules/v8/V8EntrySync.h" -#include "V8Attr.h" -#include "V8DirectoryEntrySync.h" -#include "V8FileEntrySync.h" +#include "bindings/core/v8/V8Attr.h" +#include "bindings/modules/v8/V8DirectoryEntrySync.h" +#include "bindings/modules/v8/V8FileEntrySync.h" #include "bindings/v8/V8Binding.h" #include "wtf/RefPtr.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ErrorEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ErrorEventCustom.cpp index 01ed71acdac..8021350dfbd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ErrorEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ErrorEventCustom.cpp @@ -29,25 +29,23 @@ */ #include "config.h" -#include "V8ErrorEvent.h" +#include "bindings/core/v8/V8ErrorEvent.h" -#include "RuntimeEnabledFeatures.h" -#include "V8Event.h" +#include "bindings/core/v8/V8Event.h" #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/Dictionary.h" -#include "bindings/v8/ScriptState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/ContextFeatures.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { void V8ErrorEvent::errorAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { - v8::Handle<v8::Value> error = info.Holder()->GetHiddenValue(V8HiddenPropertyName::error(info.GetIsolate())); - + v8::Handle<v8::Value> error = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::error(info.GetIsolate())); if (!error.IsEmpty()) { v8SetReturnValue(info, error); return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventCustom.cpp index d313239f485..86217c40a83 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventCustom.cpp @@ -29,16 +29,15 @@ */ #include "config.h" -#include "V8Event.h" +#include "bindings/core/v8/V8Event.h" -#include "EventHeaders.h" -#include "EventInterfaces.h" -#include "V8Clipboard.h" +#include "EventModulesHeaders.h" +#include "EventModulesInterfaces.h" +#include "bindings/core/v8/V8DataTransfer.h" #include "bindings/v8/V8Binding.h" -#include "core/dom/Clipboard.h" +#include "core/clipboard/Clipboard.h" #include "core/events/ClipboardEvent.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" namespace WebCore { @@ -67,6 +66,7 @@ v8::Handle<v8::Object> wrap(Event* event, v8::Handle<v8::Object> creationContext return V8Event::createWrapper(event, creationContext, isolate); EVENT_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE) + EVENT_MODULES_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE) return V8Event::createWrapper(event, creationContext, isolate); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventTargetCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventTargetCustom.cpp index 8bb41db3bcb..89e7b660449 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventTargetCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventTargetCustom.cpp @@ -29,10 +29,12 @@ */ #include "config.h" -#include "V8EventTarget.h" +#include "bindings/core/v8/V8EventTarget.h" -#include "EventTargetHeaders.h" -#include "EventTargetInterfaces.h" +#include "core/EventTargetHeaders.h" +#include "core/EventTargetInterfaces.h" +#include "modules/EventTargetModulesHeaders.h" +#include "modules/EventTargetModulesInterfaces.h" namespace WebCore { @@ -47,6 +49,7 @@ v8::Handle<v8::Value> toV8(EventTarget* impl, v8::Handle<v8::Object> creationCon AtomicString desiredInterface = impl->interfaceName(); EVENT_TARGET_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE) + EVENT_TARGET_MODULES_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE) ASSERT_NOT_REACHED(); return v8Undefined(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp index ecbb7815d46..d01acf369cc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp @@ -29,12 +29,11 @@ */ #include "config.h" -#include "V8File.h" +#include "bindings/core/v8/V8File.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/custom/V8BlobCustomHelpers.h" -#include "core/fileapi/BlobBuilder.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { @@ -66,7 +65,7 @@ void V8File::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) } } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, fileName, info[1]); + TOSTRING_VOID(V8StringResource<>, fileName, info[1]); V8BlobCustomHelpers::ParsedProperties properties(true); if (info.Length() > 2) { @@ -84,12 +83,14 @@ void V8File::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) properties.setDefaultLastModified(); } - BlobBuilder blobBuilder; + OwnPtr<BlobData> blobData = BlobData::create(); + blobData->setContentType(properties.contentType()); v8::Local<v8::Object> blobParts = v8::Local<v8::Object>::Cast(info[0]); - if (!V8BlobCustomHelpers::processBlobParts(blobParts, length, properties.endings(), blobBuilder, info.GetIsolate())) + if (!V8BlobCustomHelpers::processBlobParts(blobParts, length, properties.normalizeLineEndingsToNative(), *blobData, info.GetIsolate())) return; - RefPtr<File> file = blobBuilder.createFile(properties.contentType(), fileName, properties.lastModified()); + long long fileSize = blobData->length(); + RefPtrWillBeRawPtr<File> file = File::create(fileName, properties.lastModified(), BlobDataHandle::create(blobData.release(), fileSize)); v8SetReturnValue(info, file.release()); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileReaderCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileReaderCustom.cpp index c6ee39e6f4b..333040712e5 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileReaderCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileReaderCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "V8FileReader.h" +#include "bindings/core/v8/V8FileReader.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" @@ -40,12 +40,12 @@ namespace WebCore { void V8FileReader::resultAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { v8::Handle<v8::Object> holder = info.Holder(); - FileReader* imp = V8FileReader::toNative(holder); - if (imp->readType() == FileReaderLoader::ReadAsArrayBuffer) { - v8SetReturnValueFast(info, imp->arrayBufferResult(), imp); + FileReader* impl = V8FileReader::toNative(holder); + if (impl->readType() == FileReaderLoader::ReadAsArrayBuffer) { + v8SetReturnValueFast(info, impl->arrayBufferResult(), impl); return; } - v8SetReturnValueStringOrNull(info, imp->stringResult(), info.GetIsolate()); + v8SetReturnValueStringOrNull(info, impl->stringResult(), info.GetIsolate()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float32ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float32ArrayCustom.h index 17ef9710e0a..3caa7d1da2a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float32ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float32ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Float32Array> V8Float32Array; -template<> -class WrapperTypeTraits<Float32Array> : public TypedArrayWrapperTraits<Float32Array> { }; - - inline v8::Handle<v8::Object> wrap(Float32Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Float32Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float64ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float64ArrayCustom.h index 30ec270d288..0e793b6525f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float64ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float64ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Float64Array> V8Float64Array; -template<> -class WrapperTypeTraits<Float64Array> : public TypedArrayWrapperTraits<Float64Array> { }; - - inline v8::Handle<v8::Object> wrap(Float64Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Float64Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FormDataCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FormDataCustom.cpp deleted file mode 100644 index 890bf034789..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FormDataCustom.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8FormData.h" - -#include "V8Blob.h" -#include "V8HTMLFormElement.h" -#include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" -#include "core/html/DOMFormData.h" - -namespace WebCore { - -void V8FormData::appendMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - if (info.Length() < 2) { - throwError(v8SyntaxError, "Not enough arguments", info.GetIsolate()); - return; - } - - DOMFormData* domFormData = V8FormData::toNative(info.Holder()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, name, info[0]); - - v8::Handle<v8::Value> arg = info[1]; - if (V8Blob::hasInstance(arg, info.GetIsolate(), worldType(info.GetIsolate()))) { - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); - Blob* blob = V8Blob::toNative(object); - ASSERT(blob); - - String filename; - if (info.Length() >= 3) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, filenameResource, info[2]); - filename = filenameResource; - } - - domFormData->append(name, blob, filename); - } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, argString, arg); - domFormData->append(name, argString); - } -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8GeolocationCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8GeolocationCustom.cpp index 3ce2878edde..e09d99c34bd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8GeolocationCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8GeolocationCustom.cpp @@ -24,31 +24,29 @@ */ #include "config.h" -#include "V8Geolocation.h" +#include "bindings/modules/v8/V8Geolocation.h" -#include "V8PositionCallback.h" -#include "V8PositionErrorCallback.h" +#include "bindings/modules/v8/V8PositionCallback.h" +#include "bindings/modules/v8/V8PositionErrorCallback.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8Callback.h" -#include "bindings/v8/V8Utilities.h" #include "modules/geolocation/Geolocation.h" -using namespace std; using namespace WTF; namespace WebCore { -static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> value, v8::Isolate* isolate, bool& succeeded) +static PositionOptions* createPositionOptions(v8::Local<v8::Value> value, v8::Isolate* isolate, bool& succeeded, ExceptionState& exceptionState) { succeeded = true; // Create default options. - RefPtr<PositionOptions> options = PositionOptions::create(); + PositionOptions* options = PositionOptions::create(); // Argument is optional (hence undefined is allowed), and null is allowed. if (isUndefinedOrNull(value)) { // Use default options. - return options.release(); + return options; } // Given the above test, this will always yield an object. @@ -61,13 +59,13 @@ static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> va v8::Local<v8::Value> enableHighAccuracyValue = object->Get(v8AtomicString(isolate, "enableHighAccuracy")); if (enableHighAccuracyValue.IsEmpty()) { succeeded = false; - return 0; + return nullptr; } if (!enableHighAccuracyValue->IsUndefined()) { v8::Local<v8::Boolean> enableHighAccuracyBoolean = enableHighAccuracyValue->ToBoolean(); if (enableHighAccuracyBoolean.IsEmpty()) { succeeded = false; - return 0; + return nullptr; } options->setEnableHighAccuracy(enableHighAccuracyBoolean->Value()); } @@ -75,100 +73,88 @@ static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> va v8::Local<v8::Value> timeoutValue = object->Get(v8AtomicString(isolate, "timeout")); if (timeoutValue.IsEmpty()) { succeeded = false; - return 0; + return nullptr; } if (!timeoutValue->IsUndefined()) { v8::Local<v8::Number> timeoutNumber = timeoutValue->ToNumber(); if (timeoutNumber.IsEmpty()) { succeeded = false; - return 0; - } - double timeoutDouble = timeoutNumber->Value(); - // If the value is positive infinity, there's nothing to do. - if (!(std::isinf(timeoutDouble) && timeoutDouble > 0)) { - v8::Local<v8::Int32> timeoutInt32 = timeoutValue->ToInt32(); - if (timeoutInt32.IsEmpty()) { - succeeded = false; - return 0; - } - // Wrap to int32 and force non-negative to match behavior of window.setTimeout. - options->setTimeout(max(0, timeoutInt32->Value())); + return nullptr; } + if (timeoutNumber->Value() <= 0) + options->setTimeout(0); + else + options->setTimeout(toUInt32(timeoutValue, Clamp, exceptionState)); } v8::Local<v8::Value> maximumAgeValue = object->Get(v8AtomicString(isolate, "maximumAge")); if (maximumAgeValue.IsEmpty()) { succeeded = false; - return 0; + return nullptr; } if (!maximumAgeValue->IsUndefined()) { v8::Local<v8::Number> maximumAgeNumber = maximumAgeValue->ToNumber(); if (maximumAgeNumber.IsEmpty()) { succeeded = false; - return 0; - } - double maximumAgeDouble = maximumAgeNumber->Value(); - if (std::isinf(maximumAgeDouble) && maximumAgeDouble > 0) { - // If the value is positive infinity, clear maximumAge. - options->clearMaximumAge(); - } else { - v8::Local<v8::Int32> maximumAgeInt32 = maximumAgeValue->ToInt32(); - if (maximumAgeInt32.IsEmpty()) { - succeeded = false; - return 0; - } - // Wrap to int32 and force non-negative to match behavior of window.setTimeout. - options->setMaximumAge(max(0, maximumAgeInt32->Value())); + return nullptr; } + if (maximumAgeNumber->Value() <= 0) + options->setMaximumAge(0); + else + options->setMaximumAge(toUInt32(maximumAgeValue, Clamp, exceptionState)); } - return options.release(); + return options; } void V8Geolocation::getCurrentPositionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { bool succeeded = false; - OwnPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8PositionCallback>(info[0], succeeded, info.GetIsolate()); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getCurrentPosition", "Geolocation", info.Holder(), info.GetIsolate()); + + OwnPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8PositionCallback>(info[0], 1, succeeded, info.GetIsolate(), exceptionState); if (!succeeded) return; ASSERT(positionCallback); // Argument is optional (hence undefined is allowed), and null is allowed. - OwnPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8PositionErrorCallback>(info[1], succeeded, info.GetIsolate(), CallbackAllowUndefined | CallbackAllowNull); + OwnPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8PositionErrorCallback>(info[1], 2, succeeded, info.GetIsolate(), exceptionState, CallbackAllowUndefined | CallbackAllowNull); if (!succeeded) return; - RefPtr<PositionOptions> positionOptions = createPositionOptions(info[2], info.GetIsolate(), succeeded); + PositionOptions* positionOptions = createPositionOptions(info[2], info.GetIsolate(), succeeded, exceptionState); if (!succeeded) return; ASSERT(positionOptions); Geolocation* geolocation = V8Geolocation::toNative(info.Holder()); - geolocation->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); + geolocation->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions); } void V8Geolocation::watchPositionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { bool succeeded = false; - OwnPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8PositionCallback>(info[0], succeeded, info.GetIsolate()); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "watchCurrentPosition", "Geolocation", info.Holder(), info.GetIsolate()); + + OwnPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8PositionCallback>(info[0], 1, succeeded, info.GetIsolate(), exceptionState); if (!succeeded) return; ASSERT(positionCallback); // Argument is optional (hence undefined is allowed), and null is allowed. - OwnPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8PositionErrorCallback>(info[1], succeeded, info.GetIsolate(), CallbackAllowUndefined | CallbackAllowNull); + OwnPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8PositionErrorCallback>(info[1], 2, succeeded, info.GetIsolate(), exceptionState, CallbackAllowUndefined | CallbackAllowNull); if (!succeeded) return; - RefPtr<PositionOptions> positionOptions = createPositionOptions(info[2], info.GetIsolate(), succeeded); + PositionOptions* positionOptions = createPositionOptions(info[2], info.GetIsolate(), succeeded, exceptionState); if (!succeeded) return; ASSERT(positionOptions); Geolocation* geolocation = V8Geolocation::toNative(info.Holder()); - int watchId = geolocation->watchPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); + int watchId = geolocation->watchPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions); v8SetReturnValue(info, watchId); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp index 670b36cbadd..c0383741326 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8HTMLAllCollection.h" +#include "bindings/core/v8/V8HTMLAllCollection.h" -#include "V8Node.h" -#include "V8NodeList.h" +#include "bindings/core/v8/V8Element.h" +#include "bindings/core/v8/V8NodeList.h" #include "bindings/v8/V8Binding.h" #include "core/dom/NamedNodesCollection.h" #include "core/html/HTMLAllCollection.h" @@ -43,7 +43,7 @@ namespace WebCore { template<class CallbackInfo> static v8::Handle<v8::Value> getNamedItems(HTMLAllCollection* collection, AtomicString name, const CallbackInfo& info) { - Vector<RefPtr<Node> > namedItems; + WillBeHeapVector<RefPtrWillBeMember<Element> > namedItems; collection->namedItems(name, namedItems); if (!namedItems.size()) @@ -62,7 +62,7 @@ static v8::Handle<v8::Value> getItem(HTMLAllCollection* collection, v8::Handle<v { v8::Local<v8::Uint32> index = argument->ToArrayIndex(); if (index.IsEmpty()) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, name, argument, v8::Undefined(info.GetIsolate())); + TOSTRING_DEFAULT(V8StringResource<>, name, argument, v8::Undefined(info.GetIsolate())); v8::Handle<v8::Value> result = getNamedItems(collection, name, info); if (result.IsEmpty()) @@ -71,29 +71,14 @@ static v8::Handle<v8::Value> getItem(HTMLAllCollection* collection, v8::Handle<v return result; } - RefPtr<Node> result = collection->item(index->Uint32Value()); + RefPtrWillBeRawPtr<Element> result = collection->item(index->Uint32Value()); return toV8(result.release(), info.Holder(), info.GetIsolate()); } void V8HTMLAllCollection::itemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - HTMLAllCollection* imp = V8HTMLAllCollection::toNative(info.Holder()); - v8SetReturnValue(info, getItem(imp, info[0], info)); -} - -void V8HTMLAllCollection::namedItemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, info[0]); - - HTMLAllCollection* imp = V8HTMLAllCollection::toNative(info.Holder()); - v8::Handle<v8::Value> result = getNamedItems(imp, name, info); - - if (result.IsEmpty()) { - v8SetReturnValueNull(info); - return; - } - - v8SetReturnValue(info, result); + HTMLAllCollection* impl = V8HTMLAllCollection::toNative(info.Holder()); + v8SetReturnValue(info, getItem(impl, info[0], info)); } void V8HTMLAllCollection::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -101,25 +86,24 @@ void V8HTMLAllCollection::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Va if (info.Length() < 1) return; - HTMLAllCollection* imp = V8HTMLAllCollection::toNative(info.Holder()); - Node* ownerNode = imp->ownerNode(); - ASSERT(ownerNode); + HTMLAllCollection* impl = V8HTMLAllCollection::toNative(info.Holder()); + Node& ownerNode = impl->ownerNode(); - UseCounter::count(ownerNode->document(), UseCounter::DocumentAllLegacyCall); + UseCounter::count(ownerNode.document(), UseCounter::DocumentAllLegacyCall); if (info.Length() == 1) { - v8SetReturnValue(info, getItem(imp, info[0], info)); + v8SetReturnValue(info, getItem(impl, info[0], info)); return; } // If there is a second argument it is the index of the item we want. - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, info[0]); + TOSTRING_VOID(V8StringResource<>, name, info[0]); v8::Local<v8::Uint32> index = info[1]->ToArrayIndex(); if (index.IsEmpty()) return; - if (Node* node = imp->namedItemWithIndex(name, index->Uint32Value())) { - v8SetReturnValueFast(info, node, imp); + if (Node* node = impl->namedItemWithIndex(name, index->Uint32Value())) { + v8SetReturnValueFast(info, node, impl); return; } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp index c69cbdde418..46a15946f72 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp @@ -30,13 +30,12 @@ */ #include "config.h" -#include "V8HTMLCanvasElement.h" +#include "bindings/core/v8/V8HTMLCanvasElement.h" -#include "V8CanvasRenderingContext2D.h" -#include "V8Node.h" -#include "V8WebGLRenderingContext.h" +#include "bindings/core/v8/V8CanvasRenderingContext2D.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8WebGLRenderingContext.h" #include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ScriptState.h" #include "bindings/v8/V8Binding.h" #include "core/html/HTMLCanvasElement.h" #include "core/html/canvas/Canvas2DContextAttributes.h" @@ -52,34 +51,34 @@ void V8HTMLCanvasElement::getContextMethodCustom(const v8::FunctionCallbackInfo< { v8::Handle<v8::Object> holder = info.Holder(); v8::Isolate* isolate = info.GetIsolate(); - HTMLCanvasElement* imp = V8HTMLCanvasElement::toNative(holder); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, contextIdResource, info[0]); + HTMLCanvasElement* impl = V8HTMLCanvasElement::toNative(holder); + TOSTRING_VOID(V8StringResource<>, contextIdResource, info[0]); String contextId = contextIdResource; RefPtr<CanvasContextAttributes> attributes; - if (contextId == "webgl" || contextId == "experimental-webgl" || contextId == "webkit-3d") { + if (contextId == "webgl" || contextId == "experimental-webgl") { RefPtr<WebGLContextAttributes> webGLAttributes = WebGLContextAttributes::create(); if (info.Length() > 1 && info[1]->IsObject()) { v8::Handle<v8::Object> jsAttributes = info[1]->ToObject(); v8::Handle<v8::String> alpha = v8AtomicString(isolate, "alpha"); - if (jsAttributes->Has(alpha)) + if (jsAttributes->Has(alpha) && !isUndefinedOrNull(jsAttributes->Get(alpha))) webGLAttributes->setAlpha(jsAttributes->Get(alpha)->BooleanValue()); v8::Handle<v8::String> depth = v8AtomicString(isolate, "depth"); - if (jsAttributes->Has(depth)) + if (jsAttributes->Has(depth) && !isUndefinedOrNull(jsAttributes->Get(depth))) webGLAttributes->setDepth(jsAttributes->Get(depth)->BooleanValue()); v8::Handle<v8::String> stencil = v8AtomicString(isolate, "stencil"); - if (jsAttributes->Has(stencil)) + if (jsAttributes->Has(stencil) && !isUndefinedOrNull(jsAttributes->Get(stencil))) webGLAttributes->setStencil(jsAttributes->Get(stencil)->BooleanValue()); v8::Handle<v8::String> antialias = v8AtomicString(isolate, "antialias"); - if (jsAttributes->Has(antialias)) + if (jsAttributes->Has(antialias) && !isUndefinedOrNull(jsAttributes->Get(antialias))) webGLAttributes->setAntialias(jsAttributes->Get(antialias)->BooleanValue()); v8::Handle<v8::String> premultipliedAlpha = v8AtomicString(isolate, "premultipliedAlpha"); - if (jsAttributes->Has(premultipliedAlpha)) + if (jsAttributes->Has(premultipliedAlpha) && !isUndefinedOrNull(jsAttributes->Get(premultipliedAlpha))) webGLAttributes->setPremultipliedAlpha(jsAttributes->Get(premultipliedAlpha)->BooleanValue()); v8::Handle<v8::String> preserveDrawingBuffer = v8AtomicString(isolate, "preserveDrawingBuffer"); - if (jsAttributes->Has(preserveDrawingBuffer)) + if (jsAttributes->Has(preserveDrawingBuffer) && !isUndefinedOrNull(jsAttributes->Get(preserveDrawingBuffer))) webGLAttributes->setPreserveDrawingBuffer(jsAttributes->Get(preserveDrawingBuffer)->BooleanValue()); v8::Handle<v8::String> failIfMajorPerformanceCaveat = v8AtomicString(isolate, "failIfMajorPerformanceCaveat"); - if (jsAttributes->Has(failIfMajorPerformanceCaveat)) + if (jsAttributes->Has(failIfMajorPerformanceCaveat) && !isUndefinedOrNull(jsAttributes->Get(failIfMajorPerformanceCaveat))) webGLAttributes->setFailIfMajorPerformanceCaveat(jsAttributes->Get(failIfMajorPerformanceCaveat)->BooleanValue()); } attributes = webGLAttributes; @@ -88,23 +87,23 @@ void V8HTMLCanvasElement::getContextMethodCustom(const v8::FunctionCallbackInfo< if (info.Length() > 1 && info[1]->IsObject()) { v8::Handle<v8::Object> jsAttributes = info[1]->ToObject(); v8::Handle<v8::String> alpha = v8AtomicString(isolate, "alpha"); - if (jsAttributes->Has(alpha)) + if (jsAttributes->Has(alpha) && !isUndefinedOrNull(jsAttributes->Get(alpha))) canvas2DAttributes->setAlpha(jsAttributes->Get(alpha)->BooleanValue()); } attributes = canvas2DAttributes; } - CanvasRenderingContext* result = imp->getContext(contextId, attributes.get()); + CanvasRenderingContext* result = impl->getContext(contextId, attributes.get()); if (!result) { v8SetReturnValueNull(info); return; } if (result->is2d()) { v8::Handle<v8::Value> v8Result = toV8(toCanvasRenderingContext2D(result), info.Holder(), info.GetIsolate()); - if (InspectorInstrumentation::canvasAgentEnabled(&imp->document())) { - ScriptState* scriptState = ScriptState::forContext(isolate->GetCurrentContext()); - ScriptObject context(scriptState, v8::Handle<v8::Object>::Cast(v8Result)); - ScriptObject wrapped = InspectorInstrumentation::wrapCanvas2DRenderingContextForInstrumentation(&imp->document(), context); - if (!wrapped.hasNoValue()) { + if (InspectorInstrumentation::canvasAgentEnabled(&impl->document())) { + ScriptState* scriptState = ScriptState::current(isolate); + ScriptValue context(scriptState, v8Result); + ScriptValue wrapped = InspectorInstrumentation::wrapCanvas2DRenderingContextForInstrumentation(&impl->document(), context); + if (!wrapped.isEmpty()) { v8SetReturnValue(info, wrapped.v8Value()); return; } @@ -114,11 +113,11 @@ void V8HTMLCanvasElement::getContextMethodCustom(const v8::FunctionCallbackInfo< } if (result->is3d()) { v8::Handle<v8::Value> v8Result = toV8(toWebGLRenderingContext(result), info.Holder(), info.GetIsolate()); - if (InspectorInstrumentation::canvasAgentEnabled(&imp->document())) { - ScriptState* scriptState = ScriptState::forContext(isolate->GetCurrentContext()); - ScriptObject glContext(scriptState, v8::Handle<v8::Object>::Cast(v8Result)); - ScriptObject wrapped = InspectorInstrumentation::wrapWebGLRenderingContextForInstrumentation(&imp->document(), glContext); - if (!wrapped.hasNoValue()) { + if (InspectorInstrumentation::canvasAgentEnabled(&impl->document())) { + ScriptState* scriptState = ScriptState::current(isolate); + ScriptValue glContext(scriptState, v8Result); + ScriptValue wrapped = InspectorInstrumentation::wrapWebGLRenderingContextForInstrumentation(&impl->document(), glContext); + if (!wrapped.isEmpty()) { v8SetReturnValue(info, wrapped.v8Value()); return; } @@ -136,7 +135,7 @@ void V8HTMLCanvasElement::toDataURLMethodCustom(const v8::FunctionCallbackInfo<v HTMLCanvasElement* canvas = V8HTMLCanvasElement::toNative(holder); ExceptionState exceptionState(ExceptionState::ExecutionContext, "toDataURL", "HTMLCanvasElement", info.Holder(), info.GetIsolate()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]); + TOSTRING_VOID(V8StringResource<>, type, info[0]); double quality; double* qualityPtr = 0; if (info.Length() > 1 && info[1]->IsNumber()) { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCollectionCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCollectionCustom.cpp index 33fd4ca1d38..05883e60cee 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCollectionCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCollectionCustom.cpp @@ -29,12 +29,12 @@ */ #include "config.h" -#include "V8HTMLCollection.h" +#include "bindings/core/v8/V8HTMLCollection.h" -#include "V8HTMLAllCollection.h" -#include "V8HTMLFormControlsCollection.h" -#include "V8HTMLOptionsCollection.h" -#include "V8Node.h" +#include "bindings/core/v8/V8HTMLAllCollection.h" +#include "bindings/core/v8/V8HTMLFormControlsCollection.h" +#include "bindings/core/v8/V8HTMLOptionsCollection.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/V8Binding.h" #include "core/html/HTMLCollection.h" @@ -45,11 +45,11 @@ v8::Handle<v8::Object> wrap(HTMLCollection* impl, v8::Handle<v8::Object> creatio ASSERT(impl); switch (impl->type()) { case FormControls: - return wrap(static_cast<HTMLFormControlsCollection*>(impl), creationContext, isolate); + return wrap(toHTMLFormControlsCollection(impl), creationContext, isolate); case SelectOptions: - return wrap(static_cast<HTMLOptionsCollection*>(impl), creationContext, isolate); + return wrap(toHTMLOptionsCollection(impl), creationContext, isolate); case DocAll: - return wrap(static_cast<HTMLAllCollection*>(impl), creationContext, isolate); + return wrap(toHTMLAllCollection(impl), creationContext, isolate); default: break; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLDocumentCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLDocumentCustom.cpp index 49f76e73080..1f1a99bf49f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLDocumentCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLDocumentCustom.cpp @@ -29,20 +29,20 @@ */ #include "config.h" -#include "V8HTMLDocument.h" +#include "bindings/core/v8/V8HTMLDocument.h" -#include "HTMLNames.h" -#include "V8HTMLAllCollection.h" -#include "V8HTMLCollection.h" -#include "V8Node.h" -#include "V8Window.h" +#include "bindings/core/v8/V8HTMLAllCollection.h" +#include "bindings/core/v8/V8HTMLCollection.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" +#include "core/HTMLNames.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLAllCollection.h" #include "core/html/HTMLCollection.h" #include "core/html/HTMLDocument.h" #include "core/html/HTMLIFrameElement.h" -#include "core/frame/Frame.h" #include "wtf/OwnPtr.h" #include "wtf/RefPtr.h" #include "wtf/StdLibExtras.h" @@ -56,15 +56,18 @@ void V8HTMLDocument::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& HTMLDocument* htmlDocument = V8HTMLDocument::toNative(info.Holder()); if (info.Length() > 2) { - if (RefPtr<Frame> frame = htmlDocument->frame()) { + if (RefPtr<LocalFrame> frame = htmlDocument->frame()) { // Fetch the global object for the frame. - v8::Local<v8::Context> context = frame->script().currentWorldContext(); + v8::Local<v8::Context> context = toV8Context(frame.get(), DOMWrapperWorld::current(info.GetIsolate())); // Bail out if we cannot get the context. if (context.IsEmpty()) return; v8::Local<v8::Object> global = context->Global(); // Get the open property of the global object. v8::Local<v8::Value> function = global->Get(v8AtomicString(info.GetIsolate(), "open")); + // Failed; return without throwing (new) exception. + if (function.IsEmpty()) + return; // If the open property is not a function throw a type error. if (!function->IsFunction()) { throwTypeError("open is not a function", info.GetIsolate()); @@ -80,7 +83,11 @@ void V8HTMLDocument::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& } } - htmlDocument->open(activeDOMWindow()->document()); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "open", "Document", info.Holder(), info.GetIsolate()); + htmlDocument->open(callingDOMWindow(info.GetIsolate())->document(), exceptionState); + if (exceptionState.throwIfNeeded()) + return; + v8SetReturnValue(info, info.Holder()); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLElementCustom.cpp index dae4512d1dc..78706afe722 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLElementCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLElementCustom.cpp @@ -29,9 +29,9 @@ */ #include "config.h" -#include "V8HTMLElement.h" +#include "bindings/core/v8/V8HTMLElement.h" -#include "V8HTMLElementWrapperFactory.h" +#include "core/V8HTMLElementWrapperFactory.h" // FIXME: should be bindings/core/v8 namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFormControlsCollectionCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFormControlsCollectionCustom.cpp deleted file mode 100644 index ab84454965f..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFormControlsCollectionCustom.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8HTMLFormControlsCollection.h" - -#include "V8Node.h" -#include "V8RadioNodeList.h" -#include "bindings/v8/V8Binding.h" -#include "core/html/HTMLCollection.h" -#include "core/html/RadioNodeList.h" - -namespace WebCore { - -template<typename CallbackInfo> -static v8::Handle<v8::Value> getNamedItems(HTMLFormControlsCollection* collection, const AtomicString& name, const CallbackInfo& info) -{ - Vector<RefPtr<Node> > namedItems; - collection->namedItems(name, namedItems); - - if (!namedItems.size()) - return v8Undefined(); - - if (namedItems.size() == 1) - return toV8(namedItems.at(0).release(), info.Holder(), info.GetIsolate()); - - return toV8(collection->ownerNode()->radioNodeList(name).get(), info.Holder(), info.GetIsolate()); -} - -void V8HTMLFormControlsCollection::namedItemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, info[0]); - HTMLFormControlsCollection* imp = V8HTMLFormControlsCollection::toNative(info.Holder()); - v8::Handle<v8::Value> result = getNamedItems(imp, name, info); - - if (result.IsEmpty()) { - v8SetReturnValueNull(info); - return; - } - - v8SetReturnValue(info, result); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFrameElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFrameElementCustom.cpp deleted file mode 100644 index 8c011d0d922..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFrameElementCustom.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007-2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8HTMLFrameElement.h" - -#include "HTMLNames.h" -#include "bindings/v8/BindingSecurity.h" -#include "bindings/v8/ExceptionState.h" -#include "bindings/v8/V8Binding.h" -#include "core/html/HTMLFrameElement.h" -#include "core/html/parser/HTMLParserIdioms.h" - -namespace WebCore { - -using namespace HTMLNames; - -void V8HTMLFrameElement::locationAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - HTMLFrameElement* frame = V8HTMLFrameElement::toNative(info.Holder()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, locationValue, value); - - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); - if (protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(locationValue)) && !BindingSecurity::shouldAllowAccessToFrame(frame->contentFrame(), exceptionState)) { - exceptionState.throwIfNeeded(); - return; - } - - frame->setLocation(locationValue); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp index 094bf4acc8b..08ffb16adbd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp @@ -29,12 +29,11 @@ */ #include "config.h" -#include "V8HTMLOptionsCollection.h" +#include "bindings/core/v8/V8HTMLOptionsCollection.h" -#include "V8HTMLOptionElement.h" -#include "V8Node.h" -#include "V8NodeList.h" -#include "bindings/v8/ExceptionMessages.h" +#include "bindings/core/v8/V8HTMLOptionElement.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8NodeList.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" #include "core/dom/ExceptionCode.h" @@ -45,50 +44,23 @@ namespace WebCore { -template<typename CallbackInfo> -static void getNamedItems(HTMLOptionsCollection* collection, const AtomicString& name, const CallbackInfo& info) -{ - Vector<RefPtr<Node> > namedItems; - collection->namedItems(name, namedItems); - - if (!namedItems.size()) { - v8SetReturnValueNull(info); - return; - } - - if (namedItems.size() == 1) { - v8SetReturnValueFast(info, namedItems.at(0).release(), collection); - return; - } - - v8SetReturnValueFast(info, NamedNodesCollection::create(namedItems), collection); -} - -void V8HTMLOptionsCollection::namedItemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, info[0]); - HTMLOptionsCollection* imp = V8HTMLOptionsCollection::toNative(info.Holder()); - getNamedItems(imp, name, info); -} - void V8HTMLOptionsCollection::addMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ExecutionContext, "add", "HTMLOptionsCollection", info.Holder(), info.GetIsolate()); - if (!V8HTMLOptionElement::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { + if (!V8HTMLOptionElement::hasInstance(info[0], info.GetIsolate())) { exceptionState.throwTypeError("The element provided was not an HTMLOptionElement."); } else { - HTMLOptionsCollection* imp = V8HTMLOptionsCollection::toNative(info.Holder()); + HTMLOptionsCollection* impl = V8HTMLOptionsCollection::toNative(info.Holder()); HTMLOptionElement* option = V8HTMLOptionElement::toNative(v8::Handle<v8::Object>(v8::Handle<v8::Object>::Cast(info[0]))); if (info.Length() < 2) { - imp->add(option, exceptionState); + impl->add(option, exceptionState); } else { - bool ok; - V8TRYCATCH_VOID(int, index, toInt32(info[1], ok)); - if (!ok) - exceptionState.throwTypeError("The index provided could not be interpreted as an integer."); - else - imp->add(option, index, exceptionState); + int index = toInt32(info[1], exceptionState); + if (exceptionState.throwIfNeeded()) + return; + + impl->add(option, index, exceptionState); } } @@ -97,7 +69,7 @@ void V8HTMLOptionsCollection::addMethodCustom(const v8::FunctionCallbackInfo<v8: void V8HTMLOptionsCollection::lengthAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { - HTMLOptionsCollection* imp = V8HTMLOptionsCollection::toNative(info.Holder()); + HTMLOptionsCollection* impl = V8HTMLOptionsCollection::toNative(info.Holder()); double v = value->NumberValue(); unsigned newLength = 0; ExceptionState exceptionState(ExceptionState::SetterContext, "length", "HTMLOptionsCollection", info.Holder(), info.GetIsolate()); @@ -113,7 +85,7 @@ void V8HTMLOptionsCollection::lengthAttributeSetterCustom(v8::Local<v8::Value> v if (exceptionState.throwIfNeeded()) return; - imp->setLength(newLength, exceptionState); + impl->setLength(newLength, exceptionState); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp index d29360ac3cb..ac4f4cde34c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp @@ -30,9 +30,9 @@ #include "config.h" -#include "V8HTMLAppletElement.h" -#include "V8HTMLEmbedElement.h" -#include "V8HTMLObjectElement.h" +#include "bindings/core/v8/V8HTMLAppletElement.h" +#include "bindings/core/v8/V8HTMLEmbedElement.h" +#include "bindings/core/v8/V8HTMLObjectElement.h" #include "bindings/v8/SharedPersistent.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8NPObject.h" @@ -46,8 +46,8 @@ namespace WebCore { template <class C> static void npObjectNamedGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = C::toNative(info.Holder()); - RefPtr<SharedPersistent<v8::Object> > wrapper = imp->pluginWrapper(); + HTMLPlugInElement* impl = C::toNative(info.Holder()); + RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper(); if (!wrapper) return; @@ -61,8 +61,8 @@ static void npObjectNamedGetter(v8::Local<v8::String> name, const v8::PropertyCa template <class C> static void npObjectNamedSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = C::toNative(info.Holder()); - RefPtr<SharedPersistent<v8::Object> > wrapper = imp->pluginWrapper(); + HTMLPlugInElement* impl = C::toNative(info.Holder()); + RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper(); if (!wrapper) return; @@ -105,30 +105,30 @@ void V8HTMLObjectElement::namedPropertySetterCustom(v8::Local<v8::String> name, void V8HTMLAppletElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = V8HTMLAppletElement::toNative(info.Holder()); - UseCounter::count(imp->document(), UseCounter::HTMLAppletElementLegacyCall); + HTMLPlugInElement* impl = V8HTMLAppletElement::toNative(info.Holder()); + UseCounter::count(impl->document(), UseCounter::HTMLAppletElementLegacyCall); npObjectInvokeDefaultHandler(info); } void V8HTMLEmbedElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = V8HTMLEmbedElement::toNative(info.Holder()); - UseCounter::count(imp->document(), UseCounter::HTMLEmbedElementLegacyCall); + HTMLPlugInElement* impl = V8HTMLEmbedElement::toNative(info.Holder()); + UseCounter::count(impl->document(), UseCounter::HTMLEmbedElementLegacyCall); npObjectInvokeDefaultHandler(info); } void V8HTMLObjectElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = V8HTMLObjectElement::toNative(info.Holder()); - UseCounter::count(imp->document(), UseCounter::HTMLObjectElementLegacyCall); + HTMLPlugInElement* impl = V8HTMLObjectElement::toNative(info.Holder()); + UseCounter::count(impl->document(), UseCounter::HTMLObjectElementLegacyCall); npObjectInvokeDefaultHandler(info); } template <class C> void npObjectIndexedGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = C::toNative(info.Holder()); - RefPtr<SharedPersistent<v8::Object> > wrapper = imp->pluginWrapper(); + HTMLPlugInElement* impl = C::toNative(info.Holder()); + RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper(); if (!wrapper) return; @@ -142,8 +142,8 @@ void npObjectIndexedGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Va template <class C> void npObjectIndexedSetter(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = C::toNative(info.Holder()); - RefPtr<SharedPersistent<v8::Object> > wrapper = imp->pluginWrapper(); + HTMLPlugInElement* impl = C::toNative(info.Holder()); + RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper(); if (!wrapper) return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HistoryCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HistoryCustom.cpp index 427e8776532..ec963bf1204 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HistoryCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HistoryCustom.cpp @@ -29,13 +29,13 @@ */ #include "config.h" -#include "V8History.h" +#include "bindings/core/v8/V8History.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/ExceptionCode.h" #include "core/frame/History.h" @@ -45,7 +45,7 @@ void V8History::stateAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Va { History* history = V8History::toNative(info.Holder()); - v8::Handle<v8::Value> value = info.Holder()->GetHiddenValue(V8HiddenPropertyName::state(info.GetIsolate())); + v8::Handle<v8::Value> value = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate())); if (!value.IsEmpty() && !history->stateChanged()) { v8SetReturnValue(info, value); @@ -54,42 +54,40 @@ void V8History::stateAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Va RefPtr<SerializedScriptValue> serialized = history->state(); value = serialized ? serialized->deserialize(info.GetIsolate()) : v8::Handle<v8::Value>(v8::Null(info.GetIsolate())); - info.Holder()->SetHiddenValue(V8HiddenPropertyName::state(info.GetIsolate()), value); + V8HiddenValue::setHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate()), value); v8SetReturnValue(info, value); } void V8History::pushStateMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - bool didThrow = false; - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(info[0], 0, 0, didThrow, info.GetIsolate()); - if (didThrow) + ExceptionState exceptionState(ExceptionState::ExecutionContext, "pushState", "History", info.Holder(), info.GetIsolate()); + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(info[0], 0, 0, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, title, info[1]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, url, argumentOrNull(info, 2)); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, title, info[1]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, url, argumentOrNull(info, 2)); - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); History* history = V8History::toNative(info.Holder()); - history->stateObjectAdded(historyState.release(), title, url, SameDocumentNavigationPushState, exceptionState); - info.Holder()->DeleteHiddenValue(V8HiddenPropertyName::state(info.GetIsolate())); + history->stateObjectAdded(historyState.release(), title, url, FrameLoadTypeStandard, exceptionState); + V8HiddenValue::deleteHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate())); exceptionState.throwIfNeeded(); } void V8History::replaceStateMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - bool didThrow = false; - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(info[0], 0, 0, didThrow, info.GetIsolate()); - if (didThrow) + ExceptionState exceptionState(ExceptionState::ExecutionContext, "replaceState", "History", info.Holder(), info.GetIsolate()); + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(info[0], 0, 0, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, title, info[1]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, url, argumentOrNull(info, 2)); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, title, info[1]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, url, argumentOrNull(info, 2)); - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); History* history = V8History::toNative(info.Holder()); - history->stateObjectAdded(historyState.release(), title, url, SameDocumentNavigationReplaceState, exceptionState); - info.Holder()->DeleteHiddenValue(V8HiddenPropertyName::state(info.GetIsolate())); + history->stateObjectAdded(historyState.release(), title, url, FrameLoadTypeRedirectWithLockedBackForwardList, exceptionState); + V8HiddenValue::deleteHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate())); exceptionState.throwIfNeeded(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ImageDataCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ImageDataCustom.cpp index 813731456ec..c940c7c44f8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ImageDataCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ImageDataCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "V8ImageData.h" +#include "bindings/core/v8/V8ImageData.h" #include "bindings/v8/custom/V8Uint8ClampedArrayCustom.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp index cb545e6e3a3..772649e1bfb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp @@ -29,21 +29,21 @@ */ #include "config.h" -#include "V8InjectedScriptHost.h" - -#include "V8Database.h" -#include "V8HTMLAllCollection.h" -#include "V8HTMLCollection.h" -#include "V8Node.h" -#include "V8NodeList.h" -#include "V8Storage.h" +#include "bindings/core/v8/V8InjectedScriptHost.h" + +#include "bindings/core/v8/V8EventTarget.h" +#include "bindings/core/v8/V8HTMLAllCollection.h" +#include "bindings/core/v8/V8HTMLCollection.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8NodeList.h" +#include "bindings/core/v8/V8Storage.h" +#include "bindings/modules/v8/V8Database.h" #include "bindings/v8/BindingSecurity.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ScriptDebugServer.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8AbstractEventListener.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" #include "bindings/v8/V8ScriptRunner.h" #include "bindings/v8/custom/V8Float32ArrayCustom.h" #include "bindings/v8/custom/V8Float64ArrayCustom.h" @@ -54,6 +54,8 @@ #include "bindings/v8/custom/V8Uint32ArrayCustom.h" #include "bindings/v8/custom/V8Uint8ArrayCustom.h" #include "bindings/v8/custom/V8Uint8ClampedArrayCustom.h" +#include "core/events/EventTarget.h" +#include "core/frame/LocalDOMWindow.h" #include "core/inspector/InjectedScript.h" #include "core/inspector/InjectedScriptHost.h" #include "core/inspector/InspectorDOMAgent.h" @@ -62,25 +64,22 @@ namespace WebCore { -Node* InjectedScriptHost::scriptValueAsNode(ScriptValue value) +Node* InjectedScriptHost::scriptValueAsNode(ScriptState* scriptState, ScriptValue value) { - v8::HandleScope scope(value.isolate()); + ScriptState::Scope scope(scriptState); if (!value.isObject() || value.isNull()) return 0; return V8Node::toNative(v8::Handle<v8::Object>::Cast(value.v8Value())); } -ScriptValue InjectedScriptHost::nodeAsScriptValue(ScriptState* state, Node* node) +ScriptValue InjectedScriptHost::nodeAsScriptValue(ScriptState* scriptState, Node* node) { - v8::Isolate* isolate = state->isolate(); - v8::HandleScope scope(isolate); - v8::Local<v8::Context> context = state->context(); - v8::Context::Scope contextScope(context); - - ExceptionState exceptionState(v8::Handle<v8::Object>(), isolate); - if (!BindingSecurity::shouldAllowAccessToNode(node, exceptionState)) - return ScriptValue(v8::Null(isolate), isolate); - return ScriptValue(toV8(node, v8::Handle<v8::Object>(), isolate), isolate); + ScriptState::Scope scope(scriptState); + v8::Isolate* isolate = scriptState->isolate(); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "nodeAsScriptValue", "InjectedScriptHost", scriptState->context()->Global(), isolate); + if (!BindingSecurity::shouldAllowAccessToNode(isolate, node, exceptionState)) + return ScriptValue(scriptState, v8::Null(isolate)); + return ScriptValue(scriptState, toV8(node, scriptState->context()->Global(), isolate)); } void V8InjectedScriptHost::inspectedObjectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -95,7 +94,7 @@ void V8InjectedScriptHost::inspectedObjectMethodCustom(const v8::FunctionCallbac InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); InjectedScriptHost::InspectableObject* object = host->inspectedObject(info[0]->ToInt32()->Value()); - v8SetReturnValue(info, object->get(ScriptState::current()).v8Value()); + v8SetReturnValue(info, object->get(ScriptState::current(info.GetIsolate())).v8Value()); } void V8InjectedScriptHost::internalConstructorNameMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -119,7 +118,7 @@ void V8InjectedScriptHost::isHTMLAllCollectionMethodCustom(const v8::FunctionCal return; } - v8SetReturnValue(info, V8HTMLAllCollection::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))); + v8SetReturnValue(info, V8HTMLAllCollection::hasInstance(info[0], info.GetIsolate())); } void V8InjectedScriptHost::typeMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -153,32 +152,31 @@ void V8InjectedScriptHost::typeMethodCustom(const v8::FunctionCallbackInfo<v8::V v8SetReturnValue(info, v8AtomicString(isolate, "regexp")); return; } - WrapperWorldType currentWorldType = worldType(isolate); - if (V8Node::hasInstance(value, isolate, currentWorldType)) { + if (V8Node::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "node")); return; } - if (V8NodeList::hasInstance(value, isolate, currentWorldType)) { + if (V8NodeList::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } - if (V8HTMLCollection::hasInstance(value, isolate, currentWorldType)) { + if (V8HTMLCollection::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } - if (V8Int8Array::hasInstance(value, isolate, currentWorldType) || V8Int16Array::hasInstance(value, isolate, currentWorldType) || V8Int32Array::hasInstance(value, isolate, currentWorldType)) { + if (V8Int8Array::hasInstance(value, isolate) || V8Int16Array::hasInstance(value, isolate) || V8Int32Array::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } - if (V8Uint8Array::hasInstance(value, isolate, currentWorldType) || V8Uint16Array::hasInstance(value, isolate, currentWorldType) || V8Uint32Array::hasInstance(value, isolate, currentWorldType)) { + if (V8Uint8Array::hasInstance(value, isolate) || V8Uint16Array::hasInstance(value, isolate) || V8Uint32Array::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } - if (V8Float32Array::hasInstance(value, isolate, currentWorldType) || V8Float64Array::hasInstance(value, isolate, currentWorldType)) { + if (V8Float32Array::hasInstance(value, isolate) || V8Float64Array::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } - if (V8Uint8ClampedArray::hasInstance(value, isolate, currentWorldType)) { + if (V8Uint8ClampedArray::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } @@ -207,12 +205,12 @@ void V8InjectedScriptHost::functionDetailsMethodCustom(const v8::FunctionCallbac int lineNumber = function->GetScriptLineNumber(); int columnNumber = function->GetScriptColumnNumber(); - v8::Local<v8::Object> location = v8::Object::New(); - location->Set(v8AtomicString(isolate, "lineNumber"), v8::Integer::New(lineNumber, isolate)); - location->Set(v8AtomicString(isolate, "columnNumber"), v8::Integer::New(columnNumber, isolate)); - location->Set(v8AtomicString(isolate, "scriptId"), v8::Integer::New(function->ScriptId(), isolate)->ToString()); + v8::Local<v8::Object> location = v8::Object::New(isolate); + location->Set(v8AtomicString(isolate, "lineNumber"), v8::Integer::New(isolate, lineNumber)); + location->Set(v8AtomicString(isolate, "columnNumber"), v8::Integer::New(isolate, columnNumber)); + location->Set(v8AtomicString(isolate, "scriptId"), v8::Integer::New(isolate, function->ScriptId())->ToString()); - v8::Local<v8::Object> result = v8::Object::New(); + v8::Local<v8::Object> result = v8::Object::New(isolate); result->Set(v8AtomicString(isolate, "location"), location); if (!setFunctionName(result, function->GetDisplayName(), isolate) @@ -241,7 +239,7 @@ void V8InjectedScriptHost::getInternalPropertiesMethodCustom(const v8::FunctionC v8SetReturnValue(info, debugServer.getInternalProperties(object)); } -static v8::Handle<v8::Array> getJSListenerFunctions(Document* document, const EventListenerInfo& listenerInfo, v8::Isolate* isolate) +static v8::Handle<v8::Array> getJSListenerFunctions(ExecutionContext* executionContext, const EventListenerInfo& listenerInfo, v8::Isolate* isolate) { v8::Local<v8::Array> result = v8::Array::New(isolate); size_t handlersCount = listenerInfo.eventListenerVector.size(); @@ -252,7 +250,7 @@ static v8::Handle<v8::Array> getJSListenerFunctions(Document* document, const Ev continue; } V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener.get()); - v8::Local<v8::Context> context = toV8Context(document, v8Listener->world()); + v8::Local<v8::Context> context = toV8Context(executionContext, v8Listener->world()); // Hide listeners from other contexts. if (context != isolate->GetCurrentContext()) continue; @@ -260,12 +258,12 @@ static v8::Handle<v8::Array> getJSListenerFunctions(Document* document, const Ev { // getListenerObject() may cause JS in the event attribute to get compiled, potentially unsuccessfully. v8::TryCatch block; - function = v8Listener->getListenerObject(document); + function = v8Listener->getListenerObject(executionContext); if (block.HasCaught()) continue; } ASSERT(!function.IsEmpty()); - v8::Local<v8::Object> listenerEntry = v8::Object::New(); + v8::Local<v8::Object> listenerEntry = v8::Object::New(isolate); listenerEntry->Set(v8AtomicString(isolate, "listener"), function); listenerEntry->Set(v8AtomicString(isolate, "useCapture"), v8::Boolean::New(isolate, listenerInfo.eventListenerVector[i].useCapture)); result->Set(v8::Number::New(isolate, outputIndex++), listenerEntry); @@ -278,20 +276,24 @@ void V8InjectedScriptHost::getEventListenersMethodCustom(const v8::FunctionCallb if (info.Length() < 1) return; + v8::Local<v8::Value> value = info[0]; - if (!V8Node::hasInstance(value, info.GetIsolate(), worldType(info.GetIsolate()))) - return; - Node* node = V8Node::toNative(value->ToObject()); - if (!node) + EventTarget* target = V8EventTarget::toNativeWithTypeCheck(info.GetIsolate(), value); + + // We need to handle a LocalDOMWindow specially, because a LocalDOMWindow wrapper exists on a prototype chain. + if (!target) + target = toDOMWindow(value, info.GetIsolate()); + + if (!target || !target->executionContext()) return; InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); Vector<EventListenerInfo> listenersArray; - host->getEventListenersImpl(node, listenersArray); + host->getEventListenersImpl(target, listenersArray); - v8::Local<v8::Object> result = v8::Object::New(); + v8::Local<v8::Object> result = v8::Object::New(info.GetIsolate()); for (size_t i = 0; i < listenersArray.size(); ++i) { - v8::Handle<v8::Array> listeners = getJSListenerFunctions(&node->document(), listenersArray[i], info.GetIsolate()); + v8::Handle<v8::Array> listeners = getJSListenerFunctions(target->executionContext(), listenersArray[i], info.GetIsolate()); if (!listeners->Length()) continue; AtomicString eventType = listenersArray[i].eventType; @@ -307,34 +309,10 @@ void V8InjectedScriptHost::inspectMethodCustom(const v8::FunctionCallbackInfo<v8 return; InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); - ScriptValue object(info[0], info.GetIsolate()); - ScriptValue hints(info[1], info.GetIsolate()); - host->inspectImpl(object.toJSONValue(ScriptState::current()), hints.toJSONValue(ScriptState::current())); -} - -void V8InjectedScriptHost::databaseIdMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - if (info.Length() > 0 && V8Database::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - Database* database = V8Database::toNative(v8::Handle<v8::Object>::Cast(info[0])); - if (database) { - InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); { - v8SetReturnValueStringOrUndefined(info, host->databaseIdImpl(database), info.GetIsolate()); - return; - } - } - } -} - -void V8InjectedScriptHost::storageIdMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - if (info.Length() > 0 && V8Storage::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - Storage* storage = V8Storage::toNative(v8::Handle<v8::Object>::Cast(info[0])); - if (storage) { - InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); - v8SetReturnValueStringOrUndefined(info, host->storageIdImpl(storage), info.GetIsolate()); - return; - } - } + ScriptState* scriptState = ScriptState::current(info.GetIsolate()); + ScriptValue object(scriptState, info[0]); + ScriptValue hints(scriptState, info[1]); + host->inspectImpl(object.toJSONValue(scriptState), hints.toJSONValue(scriptState)); } void V8InjectedScriptHost::evaluateMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -351,7 +329,7 @@ void V8InjectedScriptHost::evaluateMethodCustom(const v8::FunctionCallbackInfo<v return; } - ASSERT(!isolate->GetCurrentContext().IsEmpty()); + ASSERT(isolate->InContext()); v8::TryCatch tryCatch; v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(expression, info.GetIsolate()); if (tryCatch.HasCaught()) { @@ -445,4 +423,25 @@ void V8InjectedScriptHost::unmonitorFunctionMethodCustom(const v8::FunctionCallb host->unmonitorFunction(scriptId, lineNumber, columnNumber); } +void V8InjectedScriptHost::suppressWarningsAndCallMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + if (info.Length() < 2 || !info[0]->IsObject() || !info[1]->IsFunction()) + return; + + InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); + ScriptDebugServer& debugServer = host->scriptDebugServer(); + debugServer.muteWarningsAndDeprecations(); + + v8::Handle<v8::Object> receiver = v8::Handle<v8::Object>::Cast(info[0]); + v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(info[1]); + size_t argc = info.Length() - 2; + OwnPtr<v8::Handle<v8::Value>[]> argv = adoptArrayPtr(new v8::Handle<v8::Value>[argc]); + for (size_t i = 0; i < argc; ++i) + argv[i] = info[i + 2]; + + v8::Local<v8::Value> result = function->Call(receiver, argc, argv.get()); + debugServer.unmuteWarningsAndDeprecations(); + v8SetReturnValue(info, result); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptManager.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptManager.cpp index fbe5295d1af..fbeffc2fc2a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptManager.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptManager.cpp @@ -31,17 +31,17 @@ #include "config.h" #include "core/inspector/InjectedScriptManager.h" -#include "V8InjectedScriptHost.h" -#include "V8Window.h" +#include "bindings/core/v8/V8InjectedScriptHost.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/BindingSecurity.h" #include "bindings/v8/ScopedPersistent.h" #include "bindings/v8/ScriptDebugServer.h" -#include "bindings/v8/ScriptObject.h" +#include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ObjectConstructor.h" #include "bindings/v8/V8ScriptRunner.h" #include "core/inspector/InjectedScriptHost.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "wtf/RefPtr.h" namespace WebCore { @@ -53,12 +53,12 @@ struct InjectedScriptManager::CallbackData { static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHost* host, v8::Isolate* isolate) { - v8::Local<v8::Function> function = V8InjectedScriptHost::domTemplate(isolate, MainWorld)->GetFunction(); + v8::Local<v8::Function> function = V8InjectedScriptHost::domTemplate(isolate)->GetFunction(); if (function.IsEmpty()) { // Return if allocation failed. return v8::Local<v8::Object>(); } - v8::Local<v8::Object> instanceTemplate = V8ObjectConstructor::newInstance(function); + v8::Local<v8::Object> instanceTemplate = V8ObjectConstructor::newInstance(isolate, function); if (instanceTemplate.IsEmpty()) { // Avoid setting the wrapper if allocation failed. return v8::Local<v8::Object>(); @@ -73,21 +73,18 @@ static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHos return instanceTemplate; } -ScriptObject InjectedScriptManager::createInjectedScript(const String& scriptSource, ScriptState* inspectedScriptState, int id) +ScriptValue InjectedScriptManager::createInjectedScript(const String& scriptSource, ScriptState* inspectedScriptState, int id) { v8::Isolate* isolate = inspectedScriptState->isolate(); - v8::HandleScope handleScope(isolate); - - v8::Local<v8::Context> inspectedContext = inspectedScriptState->context(); - v8::Context::Scope contextScope(inspectedContext); + ScriptState::Scope scope(inspectedScriptState); // Call custom code to create InjectedScripHost wrapper specific for the context // instead of calling toV8() that would create the // wrapper in the current context. // FIXME: make it possible to use generic bindings factory for InjectedScriptHost. - v8::Local<v8::Object> scriptHostWrapper = createInjectedScriptHostV8Wrapper(m_injectedScriptHost.get(), inspectedContext->GetIsolate()); + v8::Local<v8::Object> scriptHostWrapper = createInjectedScriptHostV8Wrapper(m_injectedScriptHost.get(), inspectedScriptState->isolate()); if (scriptHostWrapper.IsEmpty()) - return ScriptObject(); + return ScriptValue(); // Inject javascript into the context. The compiled script is supposed to evaluate into // a single anonymous function(it's anonymous to avoid cluttering the global object with @@ -98,28 +95,24 @@ ScriptObject InjectedScriptManager::createInjectedScript(const String& scriptSou ASSERT(!value.IsEmpty()); ASSERT(value->IsFunction()); - v8::Local<v8::Object> windowGlobal = inspectedContext->Global(); - v8::Handle<v8::Value> info[] = { scriptHostWrapper, windowGlobal, v8::Number::New(inspectedContext->GetIsolate(), id) }; - v8::Local<v8::Value> injectedScriptValue = V8ScriptRunner::callInternalFunction(v8::Local<v8::Function>::Cast(value), windowGlobal, WTF_ARRAY_LENGTH(info), info, inspectedContext->GetIsolate()); - return ScriptObject(inspectedScriptState, v8::Handle<v8::Object>::Cast(injectedScriptValue)); + v8::Local<v8::Object> windowGlobal = inspectedScriptState->context()->Global(); + v8::Handle<v8::Value> info[] = { scriptHostWrapper, windowGlobal, v8::Number::New(inspectedScriptState->isolate(), id) }; + v8::Local<v8::Value> injectedScriptValue = V8ScriptRunner::callInternalFunction(v8::Local<v8::Function>::Cast(value), windowGlobal, WTF_ARRAY_LENGTH(info), info, inspectedScriptState->isolate()); + return ScriptValue(inspectedScriptState, injectedScriptValue); } bool InjectedScriptManager::canAccessInspectedWindow(ScriptState* scriptState) { - v8::HandleScope handleScope(scriptState->isolate()); - v8::Local<v8::Context> context = scriptState->context(); - v8::Local<v8::Object> global = context->Global(); + ScriptState::Scope scope(scriptState); + v8::Local<v8::Object> global = scriptState->context()->Global(); if (global.IsEmpty()) return false; - v8::Handle<v8::Object> holder = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), MainWorld)); - if (holder.IsEmpty()) - holder = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), IsolatedWorld)); + v8::Handle<v8::Object> holder = V8Window::findInstanceInPrototypeChain(global, scriptState->isolate()); if (holder.IsEmpty()) return false; - Frame* frame = V8Window::toNative(holder)->frame(); + LocalFrame* frame = V8Window::toNative(holder)->frame(); - v8::Context::Scope contextScope(context); - return BindingSecurity::shouldAllowAccessToFrame(frame, DoNotReportSecurityError); + return BindingSecurity::shouldAllowAccessToFrame(scriptState->isolate(), frame, DoNotReportSecurityError); } void InjectedScriptManager::setWeakCallback(const v8::WeakCallbackData<v8::Object, InjectedScriptManager::CallbackData>& data) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp index 6fef29ec312..439e9347ee3 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp @@ -29,9 +29,9 @@ */ #include "config.h" -#include "V8InspectorFrontendHost.h" +#include "bindings/core/v8/V8InspectorFrontendHost.h" -#include "V8MouseEvent.h" +#include "bindings/core/v8/V8MouseEvent.h" #include "bindings/v8/V8Binding.h" #include "core/inspector/InspectorController.h" #include "core/inspector/InspectorFrontendClient.h" @@ -80,7 +80,7 @@ static bool populateContextMenuItems(v8::Local<v8::Array>& itemArray, ContextMen v8::Local<v8::Array> subItemsArray = v8::Local<v8::Array>::Cast(subItems); if (!populateContextMenuItems(subItemsArray, subMenu, isolate)) return false; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, labelString, label, false); + TOSTRING_DEFAULT(V8StringResource<WithNullCheck>, labelString, label, false); ContextMenuItem item(SubmenuType, ContextMenuItemCustomTagNoAction, labelString, @@ -88,7 +88,7 @@ static bool populateContextMenuItems(v8::Local<v8::Array>& itemArray, ContextMen menu.appendItem(item); } else { ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id->ToInt32()->Value()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, labelString, label, false); + TOSTRING_DEFAULT(V8StringResource<WithNullCheck>, labelString, label, false); ContextMenuItem menuItem((typeString == "checkbox" ? CheckableActionType : ActionType), typedId, labelString); if (checked->IsBoolean()) menuItem.setChecked(checked->ToBoolean()->Value()); @@ -143,10 +143,5 @@ void V8InspectorFrontendHost::recordPanelShownMethodCustom(const v8::FunctionCal histogramEnumeration("DevTools.PanelShown", info, 20); } -void V8InspectorFrontendHost::recordSettingChangedMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - histogramEnumeration("DevTools.SettingChanged", info, 100); -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int16ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int16ArrayCustom.h index 30f5f5864d4..58aab8bb3ae 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int16ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int16ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Int16Array> V8Int16Array; -template<> -class WrapperTypeTraits<Int16Array> : public TypedArrayWrapperTraits<Int16Array> { }; - - inline v8::Handle<v8::Object> wrap(Int16Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Int16Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int32ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int32ArrayCustom.h index bbb4aafc94d..6c29dca3988 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int32ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int32ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Int32Array> V8Int32Array; -template<> -class WrapperTypeTraits<Int32Array> : public TypedArrayWrapperTraits<Int32Array> { }; - - inline v8::Handle<v8::Object> wrap(Int32Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Int32Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int8ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int8ArrayCustom.h index 31a9e356ea4..e8783171357 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int8ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int8ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Int8Array> V8Int8Array; -template<> -class WrapperTypeTraits<Int8Array> : public TypedArrayWrapperTraits<Int8Array> { }; - - inline v8::Handle<v8::Object> wrap(Int8Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Int8Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp index 0f1a60ad709..c379d9a50dc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "V8JavaScriptCallFrame.h" +#include "bindings/core/v8/V8JavaScriptCallFrame.h" #include "bindings/v8/V8Binding.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8LocationCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8LocationCustom.cpp index a9009c9f335..58835d5f127 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8LocationCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8LocationCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "V8Location.h" +#include "bindings/core/v8/V8Location.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MIDIInputCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MIDIInputCustom.cpp deleted file mode 100644 index 6ad179c447f..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MIDIInputCustom.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8MIDIInput.h" - -#include "V8MIDIAccess.h" -#include "bindings/v8/V8HiddenPropertyName.h" - -namespace WebCore { - -v8::Handle<v8::Object> wrap(MIDIInput* input, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(input); - ASSERT(!DOMDataStore::containsWrapper<V8MIDIInput>(input, isolate)); - - v8::Handle<v8::Object> wrapper = V8MIDIInput::createWrapper(input, creationContext, isolate); - - if (input->midiAccess()) - V8HiddenPropertyName::setNamedHiddenReference(wrapper, "access", toV8(input->midiAccess(), creationContext, isolate)); - - return wrapper; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageChannelCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageChannelCustom.cpp index 67ec60fbd92..d39c588710d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageChannelCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageChannelCustom.cpp @@ -29,12 +29,11 @@ */ #include "config.h" -#include "V8MessageChannel.h" +#include "bindings/core/v8/V8MessageChannel.h" -#include "V8MessagePort.h" +#include "bindings/core/v8/V8MessagePort.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" -#include "bindings/v8/V8Utilities.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/MessageChannel.h" #include "core/workers/WorkerGlobalScope.h" #include "wtf/RefPtr.h" @@ -43,17 +42,17 @@ namespace WebCore { void V8MessageChannel::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - ExecutionContext* context = getExecutionContext(); + ExecutionContext* context = currentExecutionContext(info.GetIsolate()); - RefPtr<MessageChannel> obj = MessageChannel::create(context); + RefPtrWillBeRawPtr<MessageChannel> obj = MessageChannel::create(context); v8::Local<v8::Object> wrapper = info.Holder(); // Create references from the MessageChannel wrapper to the two // MessagePort wrappers to make sure that the MessagePort wrappers // stay alive as long as the MessageChannel wrapper is around. - V8HiddenPropertyName::setNamedHiddenReference(wrapper, "port1", toV8(obj->port1(), info.Holder(), info.GetIsolate())); - V8HiddenPropertyName::setNamedHiddenReference(wrapper, "port2", toV8(obj->port2(), info.Holder(), info.GetIsolate())); + V8HiddenValue::setHiddenValue(info.GetIsolate(), wrapper, V8HiddenValue::port1(info.GetIsolate()), toV8(obj->port1(), info.Holder(), info.GetIsolate())); + V8HiddenValue::setHiddenValue(info.GetIsolate(), wrapper, V8HiddenValue::port2(info.GetIsolate()), toV8(obj->port2(), info.Holder(), info.GetIsolate())); V8DOMWrapper::associateObjectWithWrapper<V8MessageChannel>(obj.release(), &wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); info.GetReturnValue().Set(wrapper); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageEventCustom.cpp index 9060e643728..145af08fab3 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageEventCustom.cpp @@ -29,19 +29,50 @@ */ #include "config.h" -#include "V8MessageEvent.h" +#include "bindings/core/v8/V8MessageEvent.h" -#include "V8Blob.h" -#include "V8MessagePort.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Blob.h" +#include "bindings/core/v8/V8MessagePort.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" #include "core/events/MessageEvent.h" namespace WebCore { +// Ensures a wrapper is created for the data to return now so that V8 knows how +// much memory is used via the wrapper. To keep the wrapper alive, it's set to +// the wrapper of the MessageEvent as a hidden value. +static void ensureWrapperCreatedAndAssociated(MessageEvent* eventImpl, v8::Handle<v8::Object> eventWrapper, v8::Isolate* isolate) +{ + switch (eventImpl->dataType()) { + case MessageEvent::DataTypeScriptValue: + case MessageEvent::DataTypeSerializedScriptValue: + break; + case MessageEvent::DataTypeString: { + String stringValue = eventImpl->dataAsString(); + V8HiddenValue::setHiddenValue(isolate, eventWrapper, V8HiddenValue::stringData(isolate), v8String(isolate, stringValue)); + break; + } + case MessageEvent::DataTypeBlob: + break; + case MessageEvent::DataTypeArrayBuffer: + V8HiddenValue::setHiddenValue(isolate, eventWrapper, V8HiddenValue::arrayBufferData(isolate), toV8(eventImpl->dataAsArrayBuffer(), eventWrapper, isolate)); + break; + } +} + +v8::Handle<v8::Object> wrap(MessageEvent* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +{ + ASSERT(impl); + ASSERT(!DOMDataStore::containsWrapper<V8MessageEvent>(impl, isolate)); + v8::Handle<v8::Object> wrapper = V8MessageEvent::createWrapper(impl, creationContext, isolate); + ensureWrapperCreatedAndAssociated(impl, wrapper, isolate); + return wrapper; +} + void V8MessageEvent::dataAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { MessageEvent* event = V8MessageEvent::toNative(info.Holder()); @@ -49,12 +80,12 @@ void V8MessageEvent::dataAttributeGetterCustom(const v8::PropertyCallbackInfo<v8 v8::Handle<v8::Value> result; switch (event->dataType()) { case MessageEvent::DataTypeScriptValue: { - result = info.Holder()->GetHiddenValue(V8HiddenPropertyName::data(info.GetIsolate())); + result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::data(info.GetIsolate())); if (result.IsEmpty()) { if (!event->dataAsSerializedScriptValue()) { // If we're in an isolated world and the event was created in the main world, // we need to find the 'data' property on the main world wrapper and clone it. - v8::Local<v8::Value> mainWorldData = getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenPropertyName::data(info.GetIsolate())); + v8::Local<v8::Value> mainWorldData = V8HiddenValue::getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenValue::data(info.GetIsolate())); if (!mainWorldData.IsEmpty()) event->setSerializedData(SerializedScriptValue::createAndSwallowExceptions(mainWorldData, info.GetIsolate())); } @@ -76,8 +107,11 @@ void V8MessageEvent::dataAttributeGetterCustom(const v8::PropertyCallbackInfo<v8 break; case MessageEvent::DataTypeString: { - String stringValue = event->dataAsString(); - result = v8String(info.GetIsolate(), stringValue); + result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::stringData(info.GetIsolate())); + if (result.IsEmpty()) { + String stringValue = event->dataAsString(); + result = v8String(info.GetIsolate(), stringValue); + } break; } @@ -86,12 +120,14 @@ void V8MessageEvent::dataAttributeGetterCustom(const v8::PropertyCallbackInfo<v8 break; case MessageEvent::DataTypeArrayBuffer: - result = toV8(event->dataAsArrayBuffer(), info.Holder(), info.GetIsolate()); + result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::arrayBufferData(info.GetIsolate())); + if (result.IsEmpty()) + result = toV8(event->dataAsArrayBuffer(), info.Holder(), info.GetIsolate()); break; } // Overwrite the data attribute so it returns the cached result in future invocations. - // This custom handler (dataAccessGetter) will not be called again. + // This custom getter handler will not be called again. v8::PropertyAttribute dataAttr = static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly); info.Holder()->ForceSet(v8AtomicString(info.GetIsolate(), "data"), result, dataAttr); v8SetReturnValue(info, result); @@ -100,41 +136,29 @@ void V8MessageEvent::dataAttributeGetterCustom(const v8::PropertyCallbackInfo<v8 void V8MessageEvent::initMessageEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { MessageEvent* event = V8MessageEvent::toNative(info.Holder()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, typeArg, info[0]); - V8TRYCATCH_VOID(bool, canBubbleArg, info[1]->BooleanValue()); - V8TRYCATCH_VOID(bool, cancelableArg, info[2]->BooleanValue()); + TOSTRING_VOID(V8StringResource<>, typeArg, info[0]); + TONATIVE_VOID(bool, canBubbleArg, info[1]->BooleanValue()); + TONATIVE_VOID(bool, cancelableArg, info[2]->BooleanValue()); v8::Handle<v8::Value> dataArg = info[3]; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, originArg, info[4]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, lastEventIdArg, info[5]); - - DOMWindow* sourceArg = 0; - if (info[6]->IsObject()) { - v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(info[6]); - v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate()))); - if (!window.IsEmpty()) - sourceArg = V8Window::toNative(window); - } + TOSTRING_VOID(V8StringResource<>, originArg, info[4]); + TOSTRING_VOID(V8StringResource<>, lastEventIdArg, info[5]); + LocalDOMWindow* sourceArg = toDOMWindow(info[6], info.GetIsolate()); OwnPtr<MessagePortArray> portArray; - const int portArrayIndex = 7; if (!isUndefinedOrNull(info[portArrayIndex])) { portArray = adoptPtr(new MessagePortArray); - if (!getMessagePortArray(info[portArrayIndex], portArrayIndex + 1, *portArray, info.GetIsolate())) + bool success = false; + *portArray = toRefPtrNativeArray<MessagePort, V8MessagePort>(info[portArrayIndex], portArrayIndex + 1, info.GetIsolate(), &success); + if (!success) return; } event->initMessageEvent(typeArg, canBubbleArg, cancelableArg, originArg, lastEventIdArg, sourceArg, portArray.release()); if (!dataArg.IsEmpty()) { - info.Holder()->SetHiddenValue(V8HiddenPropertyName::data(info.GetIsolate()), dataArg); - if (isolatedWorldForIsolate(info.GetIsolate())) + V8HiddenValue::setHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::data(info.GetIsolate()), dataArg); + if (DOMWrapperWorld::current(info.GetIsolate()).isIsolatedWorld()) event->setSerializedData(SerializedScriptValue::createAndSwallowExceptions(dataArg, info.GetIsolate())); } } -void V8MessageEvent::webkitInitMessageEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - initMessageEventMethodCustom(info); -} - - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessagePortCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessagePortCustom.cpp index f8eb9df2abd..d368989ba93 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessagePortCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessagePortCustom.cpp @@ -29,13 +29,12 @@ */ #include "config.h" -#include "V8MessagePort.h" +#include "bindings/core/v8/V8MessagePort.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "core/dom/MessagePort.h" #include "wtf/ArrayBuffer.h" @@ -48,19 +47,14 @@ void V8MessagePort::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::V MessagePortArray portArray; ArrayBufferArray arrayBufferArray; if (info.Length() > 1) { - bool notASequence = false; const int transferablesArgIndex = 1; - if (!extractTransferables(info[transferablesArgIndex], portArray, arrayBufferArray, notASequence, info.GetIsolate())) { - if (notASequence) { - exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(transferablesArgIndex + 1)); - exceptionState.throwIfNeeded(); - } + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, portArray, arrayBufferArray, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); return; } } - bool didThrow = false; - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &portArray, &arrayBufferArray, didThrow, info.GetIsolate()); - if (didThrow) + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &portArray, &arrayBufferArray, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; messagePort->postMessage(message.release(), &portArray, exceptionState); exceptionState.throwIfNeeded(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MutationObserverCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MutationObserverCustom.cpp index f19d3eb52ff..f2e62908d48 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MutationObserverCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MutationObserverCustom.cpp @@ -29,14 +29,14 @@ */ #include "config.h" -#include "V8MutationObserver.h" +#include "bindings/core/v8/V8MutationObserver.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" +#include "bindings/v8/V8GCController.h" #include "bindings/v8/V8MutationCallback.h" -#include "bindings/v8/V8Utilities.h" #include "core/dom/MutationObserver.h" namespace WebCore { @@ -57,14 +57,23 @@ void V8MutationObserver::constructorCustom(const v8::FunctionCallbackInfo<v8::Va return; } - ExecutionContext* context = getExecutionContext(); v8::Handle<v8::Object> wrapper = info.Holder(); - OwnPtr<MutationCallback> callback = V8MutationCallback::create(v8::Handle<v8::Function>::Cast(arg), context, wrapper, info.GetIsolate()); - RefPtr<MutationObserver> observer = MutationObserver::create(callback.release()); + OwnPtr<MutationCallback> callback = V8MutationCallback::create(v8::Handle<v8::Function>::Cast(arg), wrapper, ScriptState::current(info.GetIsolate())); + RefPtrWillBeRawPtr<MutationObserver> observer = MutationObserver::create(callback.release()); V8DOMWrapper::associateObjectWithWrapper<V8MutationObserver>(observer.release(), &wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); info.GetReturnValue().Set(wrapper); } +void V8MutationObserver::visitDOMWrapper(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) +{ + MutationObserver* observer = static_cast<MutationObserver*>(object); + HashSet<Node*> observedNodes = observer->getObservedNodes(); + for (HashSet<Node*>::iterator it = observedNodes.begin(); it != observedNodes.end(); ++it) { + v8::UniqueId id(reinterpret_cast<intptr_t>(V8GCController::opaqueRootForGC(*it, isolate))); + isolate->SetReferenceFromGroup(id, wrapper); + } +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeCustom.cpp index 854eb42b1e3..159b31e303b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeCustom.cpp @@ -29,22 +29,21 @@ */ #include "config.h" -#include "V8Node.h" - -#include "V8Attr.h" -#include "V8CDATASection.h" -#include "V8Comment.h" -#include "V8Document.h" -#include "V8DocumentFragment.h" -#include "V8DocumentType.h" -#include "V8Element.h" -#include "V8Entity.h" -#include "V8HTMLElement.h" -#include "V8Notation.h" -#include "V8ProcessingInstruction.h" -#include "V8SVGElement.h" -#include "V8ShadowRoot.h" -#include "V8Text.h" +#include "bindings/core/v8/V8Node.h" + +#include "bindings/core/v8/V8Attr.h" +#include "bindings/core/v8/V8CDATASection.h" +#include "bindings/core/v8/V8Comment.h" +#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8DocumentFragment.h" +#include "bindings/core/v8/V8DocumentType.h" +#include "bindings/core/v8/V8Element.h" +#include "bindings/core/v8/V8HTMLElement.h" +#include "bindings/core/v8/V8Notation.h" +#include "bindings/core/v8/V8ProcessingInstruction.h" +#include "bindings/core/v8/V8SVGElement.h" +#include "bindings/core/v8/V8ShadowRoot.h" +#include "bindings/core/v8/V8Text.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8AbstractEventListener.h" #include "bindings/v8/V8Binding.h" @@ -62,14 +61,14 @@ namespace WebCore { void V8Node::insertBeforeMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Handle<v8::Object> holder = info.Holder(); - Node* imp = V8Node::toNative(holder); + Node* impl = V8Node::toNative(holder); CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; ExceptionState exceptionState(ExceptionState::ExecutionContext, "insertBefore", "Node", info.Holder(), info.GetIsolate()); - Node* newChild = V8Node::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - Node* refChild = V8Node::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[1])) : 0; - imp->insertBefore(newChild, refChild, exceptionState); + Node* newChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[0]); + Node* refChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[1]); + impl->insertBefore(newChild, refChild, exceptionState); if (exceptionState.throwIfNeeded()) return; v8SetReturnValue(info, info[0]); @@ -78,14 +77,14 @@ void V8Node::insertBeforeMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& void V8Node::replaceChildMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Handle<v8::Object> holder = info.Holder(); - Node* imp = V8Node::toNative(holder); + Node* impl = V8Node::toNative(holder); CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; ExceptionState exceptionState(ExceptionState::ExecutionContext, "replaceChild", "Node", info.Holder(), info.GetIsolate()); - Node* newChild = V8Node::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - Node* oldChild = V8Node::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[1])) : 0; - imp->replaceChild(newChild, oldChild, exceptionState); + Node* newChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[0]); + Node* oldChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[1]); + impl->replaceChild(newChild, oldChild, exceptionState); if (exceptionState.throwIfNeeded()) return; v8SetReturnValue(info, info[1]); @@ -94,13 +93,13 @@ void V8Node::replaceChildMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& void V8Node::removeChildMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Handle<v8::Object> holder = info.Holder(); - Node* imp = V8Node::toNative(holder); + Node* impl = V8Node::toNative(holder); CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; ExceptionState exceptionState(ExceptionState::ExecutionContext, "removeChild", "Node", info.Holder(), info.GetIsolate()); - Node* oldChild = V8Node::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - imp->removeChild(oldChild, exceptionState); + Node* oldChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[0]); + impl->removeChild(oldChild, exceptionState); if (exceptionState.throwIfNeeded()) return; v8SetReturnValue(info, info[0]); @@ -109,13 +108,13 @@ void V8Node::removeChildMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& void V8Node::appendChildMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Handle<v8::Object> holder = info.Holder(); - Node* imp = V8Node::toNative(holder); + Node* impl = V8Node::toNative(holder); CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; ExceptionState exceptionState(ExceptionState::ExecutionContext, "appendChild", "Node", info.Holder(), info.GetIsolate()); - Node* newChild = V8Node::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - imp->appendChild(newChild, exceptionState); + Node* newChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[0]); + impl->appendChild(newChild, exceptionState); if (exceptionState.throwIfNeeded()) return; v8SetReturnValue(info, info[0]); @@ -150,14 +149,8 @@ v8::Handle<v8::Object> wrap(Node* impl, v8::Handle<v8::Object> creationContext, if (impl->isShadowRoot()) return wrap(toShadowRoot(impl), creationContext, isolate); return wrap(toDocumentFragment(impl), creationContext, isolate); - case Node::ENTITY_NODE: - case Node::NOTATION_NODE: - // We never create objects of Entity and Notation. - ASSERT_NOT_REACHED(); - break; - default: - break; // ENTITY_REFERENCE_NODE or XPATH_NAMESPACE_NODE } + ASSERT_NOT_REACHED(); return V8Node::createWrapper(impl, creationContext, isolate); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8OscillatorNodeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8OscillatorNodeCustom.cpp deleted file mode 100644 index 7216a8ec56b..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8OscillatorNodeCustom.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2012, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#if ENABLE(WEB_AUDIO) -#include "V8OscillatorNode.h" - -#include "bindings/v8/V8Binding.h" -#include "modules/webaudio/OscillatorNode.h" - -namespace WebCore { - -void V8OscillatorNode::typeAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - v8::Handle<v8::Object> holder = info.Holder(); - OscillatorNode* imp = V8OscillatorNode::toNative(holder); - - if (value->IsNumber()) { - bool ok = false; - uint32_t type = toUInt32(value, ok); - if (!ok || !imp->setType(type)) - throwTypeError("Illegal OscillatorNode type", info.GetIsolate()); - return; - } - - if (value->IsString()) { - String type = toCoreString(value.As<v8::String>()); - if (type == "sine" || type == "square" || type == "sawtooth" || type == "triangle") { - imp->setType(type); - return; - } - } - - throwTypeError("Illegal OscillatorNode type", info.GetIsolate()); -} - -} // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PannerNodeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PannerNodeCustom.cpp deleted file mode 100644 index 5e10fda34cf..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PannerNodeCustom.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2012, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#if ENABLE(WEB_AUDIO) -#include "V8PannerNode.h" - -#include "bindings/v8/V8Binding.h" -#include "modules/webaudio/PannerNode.h" - -namespace WebCore { - -void V8PannerNode::panningModelAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - PannerNode* imp = V8PannerNode::toNative(info.Holder()); - - if (value->IsNumber()) { - bool ok = false; - uint32_t model = toUInt32(value, ok); - ASSERT(ok); - if (!imp->setPanningModel(model)) - throwTypeError("Illegal panningModel", info.GetIsolate()); - return; - } - - if (value->IsString()) { - String model = toCoreString(value.As<v8::String>()); - if (model == "equalpower" || model == "HRTF" || model == "soundfield") { - imp->setPanningModel(model); - return; - } - } - - throwTypeError("Illegal panningModel", info.GetIsolate()); -} - -void V8PannerNode::distanceModelAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - PannerNode* imp = V8PannerNode::toNative(info.Holder()); - - if (value->IsNumber()) { - bool ok = false; - uint32_t model = toUInt32(value, ok); - ASSERT(ok); - if (!imp->setDistanceModel(model)) - throwTypeError("Illegal distanceModel", info.GetIsolate()); - return; - } - - if (value->IsString()) { - String model = toCoreString(value.As<v8::String>()); - if (model == "linear" || model == "inverse" || model == "exponential") { - imp->setDistanceModel(model); - return; - } - } - - throwTypeError("Illegal distanceModel", info.GetIsolate()); -} - -} // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PerformanceEntryCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PerformanceEntryCustom.cpp index 15197329bae..6e1d54e0b68 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PerformanceEntryCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PerformanceEntryCustom.cpp @@ -29,11 +29,11 @@ */ #include "config.h" -#include "V8PerformanceEntry.h" +#include "bindings/core/v8/V8PerformanceEntry.h" -#include "V8PerformanceMark.h" -#include "V8PerformanceMeasure.h" -#include "V8PerformanceResourceTiming.h" +#include "bindings/core/v8/V8PerformanceMark.h" +#include "bindings/core/v8/V8PerformanceMeasure.h" +#include "bindings/core/v8/V8PerformanceResourceTiming.h" #include "core/timing/Performance.h" #include "core/timing/PerformanceMark.h" #include "core/timing/PerformanceMeasure.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PopStateEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PopStateEventCustom.cpp index 8a7b790822c..83385ca297f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PopStateEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PopStateEventCustom.cpp @@ -29,11 +29,11 @@ */ #include "config.h" -#include "V8PopStateEvent.h" +#include "bindings/core/v8/V8PopStateEvent.h" -#include "V8History.h" +#include "bindings/core/v8/V8History.h" #include "bindings/v8/SerializedScriptValue.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/events/PopStateEvent.h" #include "core/frame/History.h" @@ -42,13 +42,13 @@ namespace WebCore { // Save the state value to a hidden attribute in the V8PopStateEvent, and return it, for convenience. static v8::Handle<v8::Value> cacheState(v8::Handle<v8::Object> popStateEvent, v8::Handle<v8::Value> state, v8::Isolate* isolate) { - popStateEvent->SetHiddenValue(V8HiddenPropertyName::state(isolate), state); + V8HiddenValue::setHiddenValue(isolate, popStateEvent, V8HiddenValue::state(isolate), state); return state; } void V8PopStateEvent::stateAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { - v8::Handle<v8::Value> result = info.Holder()->GetHiddenValue(V8HiddenPropertyName::state(info.GetIsolate())); + v8::Handle<v8::Value> result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, result); @@ -61,7 +61,7 @@ void V8PopStateEvent::stateAttributeGetterCustom(const v8::PropertyCallbackInfo< if (!event->serializedState()) { // If we're in an isolated world and the event was created in the main world, // we need to find the 'state' property on the main world wrapper and clone it. - v8::Local<v8::Value> mainWorldState = getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenPropertyName::state(info.GetIsolate())); + v8::Local<v8::Value> mainWorldState = V8HiddenValue::getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenValue::state(info.GetIsolate())); if (!mainWorldState.IsEmpty()) event->setSerializedState(SerializedScriptValue::createAndSwallowExceptions(mainWorldState, info.GetIsolate())); } @@ -84,14 +84,14 @@ void V8PopStateEvent::stateAttributeGetterCustom(const v8::PropertyCallbackInfo< if (isSameState) { v8::Handle<v8::Object> v8History = toV8(history, info.Holder(), info.GetIsolate()).As<v8::Object>(); if (!history->stateChanged()) { - result = v8History->GetHiddenValue(V8HiddenPropertyName::state(info.GetIsolate())); + result = V8HiddenValue::getHiddenValue(info.GetIsolate(), v8History, V8HiddenValue::state(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, cacheState(info.Holder(), result, info.GetIsolate())); return; } } result = event->serializedState()->deserialize(info.GetIsolate()); - v8History->SetHiddenValue(V8HiddenPropertyName::state(info.GetIsolate()), result); + V8HiddenValue::setHiddenValue(info.GetIsolate(), v8History, V8HiddenValue::state(info.GetIsolate()), result); } else { result = event->serializedState()->deserialize(info.GetIsolate()); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.cpp deleted file mode 100644 index 22580d70da8..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.cpp +++ /dev/null @@ -1,794 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "bindings/v8/custom/V8PromiseCustom.h" - -#include <v8.h> -#include "V8Promise.h" -#include "bindings/v8/DOMRequestState.h" -#include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/ScriptFunctionCall.h" -#include "bindings/v8/ScriptState.h" -#include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" -#include "bindings/v8/V8PerIsolateData.h" -#include "bindings/v8/V8ScriptRunner.h" -#include "bindings/v8/WrapperTypeInfo.h" -#include "core/dom/Document.h" -#include "core/dom/ExecutionContextTask.h" -#include "core/frame/DOMWindow.h" -#include "core/workers/WorkerGlobalScope.h" -#include "platform/Task.h" -#include "wtf/Deque.h" -#include "wtf/Functional.h" -#include "wtf/Noncopyable.h" -#include "wtf/PassOwnPtr.h" - -namespace WebCore { - -namespace { - -v8::Local<v8::ObjectTemplate> cachedObjectTemplate(void* privateTemplateUniqueKey, int internalFieldCount, v8::Isolate* isolate) -{ - V8PerIsolateData* data = V8PerIsolateData::from(isolate); - WrapperWorldType currentWorldType = worldType(isolate); - v8::Handle<v8::FunctionTemplate> functionDescriptor = data->privateTemplateIfExists(currentWorldType, privateTemplateUniqueKey); - if (!functionDescriptor.IsEmpty()) - return functionDescriptor->InstanceTemplate(); - - functionDescriptor = v8::FunctionTemplate::New(isolate); - v8::Local<v8::ObjectTemplate> instanceTemplate = functionDescriptor->InstanceTemplate(); - instanceTemplate->SetInternalFieldCount(internalFieldCount); - data->setPrivateTemplate(currentWorldType, privateTemplateUniqueKey, functionDescriptor); - return instanceTemplate; -} - -v8::Local<v8::ObjectTemplate> promiseAllEnvironmentObjectTemplate(v8::Isolate* isolate) -{ - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int privateTemplateUniqueKey; - return cachedObjectTemplate(&privateTemplateUniqueKey, V8PromiseCustom::PromiseAllEnvironmentFieldCount, isolate); -} - -v8::Local<v8::ObjectTemplate> primitiveWrapperObjectTemplate(v8::Isolate* isolate) -{ - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int privateTemplateUniqueKey; - return cachedObjectTemplate(&privateTemplateUniqueKey, V8PromiseCustom::PrimitiveWrapperFieldCount, isolate); -} - -v8::Local<v8::ObjectTemplate> internalObjectTemplate(v8::Isolate* isolate) -{ - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int privateTemplateUniqueKey; - return cachedObjectTemplate(&privateTemplateUniqueKey, V8PromiseCustom::InternalFieldCount, isolate); -} - -void promiseResolveCallback(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - ASSERT(!info.Data().IsEmpty()); - v8::Local<v8::Object> promise = info.Data().As<v8::Object>(); - v8::Local<v8::Value> result = v8::Undefined(info.GetIsolate()); - if (info.Length() > 0) - result = info[0]; - - V8PromiseCustom::resolve(promise, result, info.GetIsolate()); -} - -void promiseRejectCallback(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - ASSERT(!info.Data().IsEmpty()); - v8::Local<v8::Object> promise = info.Data().As<v8::Object>(); - v8::Local<v8::Value> result = v8::Undefined(info.GetIsolate()); - if (info.Length() > 0) - result = info[0]; - - V8PromiseCustom::reject(promise, result, info.GetIsolate()); -} - -void promiseAllFulfillCallback(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - ASSERT(!info.Data().IsEmpty()); - v8::Local<v8::Object> environment = info.Data().As<v8::Object>(); - v8::Local<v8::Value> result = v8::Undefined(isolate); - if (info.Length() > 0) - result = info[0]; - - v8::Local<v8::Object> promise = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentPromiseIndex).As<v8::Object>(); - v8::Local<v8::Object> countdownWrapper = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentCountdownIndex).As<v8::Object>(); - v8::Local<v8::Integer> index = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentIndexIndex).As<v8::Integer>(); - v8::Local<v8::Array> results = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentResultsIndex).As<v8::Array>(); - - results->Set(index->Value(), result); - - v8::Local<v8::Integer> countdown = countdownWrapper->GetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex).As<v8::Integer>(); - ASSERT(countdown->Value() >= 1); - if (countdown->Value() == 1) { - V8PromiseCustom::resolve(promise, results, isolate); - return; - } - countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex, v8::Integer::New(countdown->Value() - 1, isolate)); -} - -v8::Local<v8::Object> promiseAllEnvironment(v8::Handle<v8::Object> promise, v8::Handle<v8::Object> countdownWrapper, int index, v8::Handle<v8::Array> results, v8::Isolate* isolate) -{ - v8::Local<v8::ObjectTemplate> objectTemplate = promiseAllEnvironmentObjectTemplate(isolate); - v8::Local<v8::Object> environment = objectTemplate->NewInstance(); - - environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentPromiseIndex, promise); - environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentCountdownIndex, countdownWrapper); - environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentIndexIndex, v8::Integer::New(index, isolate)); - environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentResultsIndex, results); - return environment; -} - -// Clear |internal|'s derived array. -void clearDerived(v8::Handle<v8::Object> internal, v8::Isolate* isolate) -{ - internal->SetInternalField(V8PromiseCustom::InternalFulfillCallbackIndex, v8::Array::New(isolate)); - internal->SetInternalField(V8PromiseCustom::InternalRejectCallbackIndex, v8::Array::New(isolate)); - internal->SetInternalField(V8PromiseCustom::InternalDerivedPromiseIndex, v8::Array::New(isolate)); -} - -// Add a tuple (|derivedPromise|, |onFulfilled|, |onRejected|) to -// |internal|'s derived array. -// |internal| must be a Promise internal object. -// |derivedPromise| must be a Promise instance. -// |onFulfilled| and |onRejected| can be an empty value respectively. -void addToDerived(v8::Handle<v8::Object> internal, v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Isolate* isolate) -{ - v8::Local<v8::Array> fulfillCallbacks = internal->GetInternalField(V8PromiseCustom::InternalFulfillCallbackIndex).As<v8::Array>(); - v8::Local<v8::Array> rejectCallbacks = internal->GetInternalField(V8PromiseCustom::InternalRejectCallbackIndex).As<v8::Array>(); - v8::Local<v8::Array> derivedPromises = internal->GetInternalField(V8PromiseCustom::InternalDerivedPromiseIndex).As<v8::Array>(); - - if (onFulfilled.IsEmpty()) { - fulfillCallbacks->Set(fulfillCallbacks->Length(), v8::Undefined(isolate)); - } else { - fulfillCallbacks->Set(fulfillCallbacks->Length(), onFulfilled); - } - - if (onRejected.IsEmpty()) { - rejectCallbacks->Set(rejectCallbacks->Length(), v8::Undefined(isolate)); - } else { - rejectCallbacks->Set(rejectCallbacks->Length(), onRejected); - } - - ASSERT(!derivedPromise.IsEmpty()); - derivedPromises->Set(derivedPromises->Length(), derivedPromise); - - // Since they are treated as a tuple, - // we need to guaranteed that the length of these arrays are same. - ASSERT(fulfillCallbacks->Length() == rejectCallbacks->Length() && rejectCallbacks->Length() == derivedPromises->Length()); -} - -class CallHandlerTask : public ExecutionContextTask { -public: - CallHandlerTask(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> handler, v8::Handle<v8::Value> argument, v8::Isolate* isolate, ExecutionContext* context) - : m_promise(isolate, promise) - , m_handler(isolate, handler) - , m_argument(isolate, argument) - , m_requestState(context) - { - ASSERT(!m_promise.isEmpty()); - ASSERT(!m_handler.isEmpty()); - ASSERT(!m_argument.isEmpty()); - } - virtual ~CallHandlerTask() { } - - virtual void performTask(ExecutionContext*) OVERRIDE; - -private: - ScopedPersistent<v8::Object> m_promise; - ScopedPersistent<v8::Function> m_handler; - ScopedPersistent<v8::Value> m_argument; - DOMRequestState m_requestState; -}; - -void CallHandlerTask::performTask(ExecutionContext* context) -{ - ASSERT(context); - if (context->activeDOMObjectsAreStopped()) - return; - - DOMRequestState::Scope scope(m_requestState); - v8::Isolate* isolate = m_requestState.isolate(); - v8::Handle<v8::Value> info[] = { m_argument.newLocal(isolate) }; - v8::TryCatch trycatch; - v8::Local<v8::Value> value = V8ScriptRunner::callFunction(m_handler.newLocal(isolate), context, v8::Undefined(isolate), WTF_ARRAY_LENGTH(info), info, isolate); - if (value.IsEmpty()) { - V8PromiseCustom::reject(m_promise.newLocal(isolate), trycatch.Exception(), isolate); - } else { - V8PromiseCustom::resolve(m_promise.newLocal(isolate), value, isolate); - } -} - -class UpdateDerivedTask : public ExecutionContextTask { -public: - UpdateDerivedTask(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originatorValueObject, v8::Isolate* isolate, ExecutionContext* context) - : m_promise(isolate, promise) - , m_onFulfilled(isolate, onFulfilled) - , m_onRejected(isolate, onRejected) - , m_originatorValueObject(isolate, originatorValueObject) - , m_requestState(context) - { - ASSERT(!m_promise.isEmpty()); - ASSERT(!m_originatorValueObject.isEmpty()); - } - virtual ~UpdateDerivedTask() { } - - virtual void performTask(ExecutionContext*) OVERRIDE; - -private: - ScopedPersistent<v8::Object> m_promise; - ScopedPersistent<v8::Function> m_onFulfilled; - ScopedPersistent<v8::Function> m_onRejected; - ScopedPersistent<v8::Object> m_originatorValueObject; - DOMRequestState m_requestState; -}; - -void UpdateDerivedTask::performTask(ExecutionContext* context) -{ - ASSERT(context); - if (context->activeDOMObjectsAreStopped()) - return; - - DOMRequestState::Scope scope(m_requestState); - v8::Isolate* isolate = m_requestState.isolate(); - v8::Local<v8::Object> originatorValueObject = m_originatorValueObject.newLocal(isolate); - v8::Local<v8::Value> coercedAlready = originatorValueObject->GetHiddenValue(V8HiddenPropertyName::thenableHiddenPromise(isolate)); - if (!coercedAlready.IsEmpty() && coercedAlready->IsObject()) { - ASSERT(V8PromiseCustom::isPromise(coercedAlready.As<v8::Object>(), isolate)); - V8PromiseCustom::updateDerivedFromPromise(m_promise.newLocal(isolate), m_onFulfilled.newLocal(isolate), m_onRejected.newLocal(isolate), coercedAlready.As<v8::Object>(), isolate); - return; - } - - v8::Local<v8::Value> then; - v8::TryCatch trycatch; - then = originatorValueObject->Get(v8AtomicString(isolate, "then")); - if (then.IsEmpty()) { - // If calling the [[Get]] internal method threw an exception, catch it and run updateDerivedFromReason. - V8PromiseCustom::updateDerivedFromReason(m_promise.newLocal(isolate), m_onRejected.newLocal(isolate), trycatch.Exception(), isolate); - return; - } - - if (then->IsFunction()) { - ASSERT(then->IsObject()); - v8::Local<v8::Object> coerced = V8PromiseCustom::coerceThenable(originatorValueObject, then.As<v8::Function>(), isolate); - V8PromiseCustom::updateDerivedFromPromise(m_promise.newLocal(isolate), m_onFulfilled.newLocal(isolate), m_onRejected.newLocal(isolate), coerced, isolate); - return; - } - - V8PromiseCustom::updateDerivedFromValue(m_promise.newLocal(isolate), m_onFulfilled.newLocal(isolate), originatorValueObject, isolate); -} - -// Since Promises state propagation routines are executed recursively, they cause -// stack overflow. -// (e.g. UpdateDerived -> UpdateDerivedFromValue -> SetValue -> -// PropagateToDerived -> UpdateDerived) -// -// To fix that, we introduce PromisePropagator. It holds the stack. When -// propagating the result to the derived tuples, we append the derived tuples -// to the stack. After that, we drain the stack to propagate the result to -// the stored tuples. -// -// PromisePropagator should be held on the stack and should not be held -// as other object's member. PromisePropagator holds Derived tuples. Since -// Derived tuples hold persistent handles to JS objects, retaining -// PromisePropagator in the heap causes memory leaks. -// -class PromisePropagator { - WTF_MAKE_NONCOPYABLE(PromisePropagator); -public: - PromisePropagator() { } - - void performPropagation(v8::Isolate*); - - void setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Value>, v8::Isolate*); - void setReason(v8::Handle<v8::Object> promise, v8::Handle<v8::Value>, v8::Isolate*); - void propagateToDerived(v8::Handle<v8::Object> promise, v8::Isolate*); - void updateDerived(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate*); - void updateDerivedFromValue(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Value>, v8::Isolate*); - void updateDerivedFromReason(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Value>, v8::Isolate*); - void updateDerivedFromPromise(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> promise, v8::Isolate*); - -private: - class Derived { - WTF_MAKE_NONCOPYABLE(Derived); - public: - Derived(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate) - : m_promise(isolate, promise) - , m_onFulfilled(isolate, onFulfilled) - , m_onRejected(isolate, onRejected) - , m_originator(isolate, originator) - { - ASSERT(!m_promise.isEmpty()); - ASSERT(!m_originator.isEmpty()); - } - - static PassOwnPtr<Derived> create(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate) - { - return adoptPtr(new Derived(promise, onFulfilled, onRejected, originator, isolate)); - } - - v8::Local<v8::Object> promise(v8::Isolate* isolate) const { return m_promise.newLocal(isolate); } - v8::Local<v8::Function> onFulfilled(v8::Isolate* isolate) const { return m_onFulfilled.newLocal(isolate); } - v8::Local<v8::Function> onRejected(v8::Isolate* isolate) const { return m_onRejected.newLocal(isolate); } - v8::Local<v8::Object> originator(v8::Isolate* isolate) const { return m_originator.newLocal(isolate); } - - private: - ScopedPersistent<v8::Object> m_promise; - ScopedPersistent<v8::Function> m_onFulfilled; - ScopedPersistent<v8::Function> m_onRejected; - ScopedPersistent<v8::Object> m_originator; - }; - - Deque<OwnPtr<Derived> > m_derivedStack; -}; - -void PromisePropagator::performPropagation(v8::Isolate* isolate) -{ - while (!m_derivedStack.isEmpty()) { - v8::HandleScope handleScope(isolate); - OwnPtr<Derived> derived = m_derivedStack.takeLast(); - updateDerived(derived->promise(isolate), derived->onFulfilled(isolate), derived->onRejected(isolate), derived->originator(isolate), isolate); - } -} - -void PromisePropagator::setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> value, v8::Isolate* isolate) -{ - v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise); - ASSERT(V8PromiseCustom::getState(internal) != V8PromiseCustom::Fulfilled && V8PromiseCustom::getState(internal) != V8PromiseCustom::Rejected); - V8PromiseCustom::setState(internal, V8PromiseCustom::Fulfilled, value, isolate); - propagateToDerived(promise, isolate); -} - -void PromisePropagator::setReason(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> reason, v8::Isolate* isolate) -{ - v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise); - ASSERT(V8PromiseCustom::getState(internal) != V8PromiseCustom::Fulfilled && V8PromiseCustom::getState(internal) != V8PromiseCustom::Rejected); - V8PromiseCustom::setState(internal, V8PromiseCustom::Rejected, reason, isolate); - propagateToDerived(promise, isolate); -} - -void PromisePropagator::propagateToDerived(v8::Handle<v8::Object> promise, v8::Isolate* isolate) -{ - v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise); - ASSERT(V8PromiseCustom::getState(internal) == V8PromiseCustom::Fulfilled || V8PromiseCustom::getState(internal) == V8PromiseCustom::Rejected); - v8::Local<v8::Array> fulfillCallbacks = internal->GetInternalField(V8PromiseCustom::InternalFulfillCallbackIndex).As<v8::Array>(); - v8::Local<v8::Array> rejectCallbacks = internal->GetInternalField(V8PromiseCustom::InternalRejectCallbackIndex).As<v8::Array>(); - v8::Local<v8::Array> derivedPromises = internal->GetInternalField(V8PromiseCustom::InternalDerivedPromiseIndex).As<v8::Array>(); - // Since they are treated as a tuple, - // we need to guaranteed that the length of these arrays are same. - ASSERT(fulfillCallbacks->Length() == rejectCallbacks->Length() && rejectCallbacks->Length() == derivedPromises->Length()); - - // Append Derived tuple to the stack in reverse order. - for (uint32_t count = 0, length = derivedPromises->Length(); count < length; ++count) { - uint32_t i = length - count - 1; - v8::Local<v8::Object> derivedPromise = derivedPromises->Get(i).As<v8::Object>(); - - v8::Local<v8::Function> onFulfilled, onRejected; - v8::Local<v8::Value> onFulfilledValue = fulfillCallbacks->Get(i); - if (onFulfilledValue->IsFunction()) { - onFulfilled = onFulfilledValue.As<v8::Function>(); - } - v8::Local<v8::Value> onRejectedValue = rejectCallbacks->Get(i); - if (onRejectedValue->IsFunction()) { - onRejected = onRejectedValue.As<v8::Function>(); - } - - m_derivedStack.append(Derived::create(derivedPromise, onFulfilled, onRejected, promise, isolate)); - } - clearDerived(internal, isolate); -} - -void PromisePropagator::updateDerivedFromValue(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Value> value, v8::Isolate* isolate) -{ - if (!onFulfilled.IsEmpty()) { - V8PromiseCustom::callHandler(derivedPromise, onFulfilled, value, isolate); - } else { - setValue(derivedPromise, value, isolate); - } -} - -void PromisePropagator::updateDerivedFromReason(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Value> reason, v8::Isolate* isolate) -{ - if (!onRejected.IsEmpty()) { - V8PromiseCustom::callHandler(derivedPromise, onRejected, reason, isolate); - } else { - setReason(derivedPromise, reason, isolate); - } -} - -void PromisePropagator::updateDerived(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate) -{ - v8::Local<v8::Object> originatorInternal = V8PromiseCustom::getInternal(originator); - V8PromiseCustom::PromiseState originatorState = V8PromiseCustom::getState(originatorInternal); - ASSERT(originatorState == V8PromiseCustom::Fulfilled || originatorState == V8PromiseCustom::Rejected); - v8::Local<v8::Value> originatorValue = originatorInternal->GetInternalField(V8PromiseCustom::InternalResultIndex); - if (originatorState == V8PromiseCustom::Fulfilled) { - if (originatorValue->IsObject()) { - ExecutionContext* executionContext = getExecutionContext(); - ASSERT(executionContext && executionContext->isContextThread()); - executionContext->postTask(adoptPtr(new UpdateDerivedTask(derivedPromise, onFulfilled, onRejected, originatorValue.As<v8::Object>(), isolate, executionContext))); - } else { - updateDerivedFromValue(derivedPromise, onFulfilled, originatorValue, isolate); - } - } else { - updateDerivedFromReason(derivedPromise, onRejected, originatorValue, isolate); - } -} - -void PromisePropagator::updateDerivedFromPromise(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> promise, v8::Isolate* isolate) -{ - v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise); - V8PromiseCustom::PromiseState state = V8PromiseCustom::getState(internal); - if (state == V8PromiseCustom::Fulfilled || state == V8PromiseCustom::Rejected) { - updateDerived(derivedPromise, onFulfilled, onRejected, promise, isolate); - } else { - addToDerived(internal, derivedPromise, onFulfilled, onRejected, isolate); - } -} - -} // namespace - -void V8Promise::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8SetReturnValue(info, v8::Local<v8::Value>()); - v8::Isolate* isolate = info.GetIsolate(); - if (!info.Length() || !info[0]->IsFunction()) { - throwTypeError("Promise constructor takes a function argument", isolate); - return; - } - v8::Local<v8::Function> init = info[0].As<v8::Function>(); - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate); - v8::Handle<v8::Value> argv[] = { - createClosure(promiseResolveCallback, promise, isolate), - createClosure(promiseRejectCallback, promise, isolate) - }; - v8::TryCatch trycatch; - if (V8ScriptRunner::callFunction(init, getExecutionContext(), v8::Undefined(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) { - // An exception is thrown. Reject the promise if its resolved flag is unset. - V8PromiseCustom::reject(promise, trycatch.Exception(), isolate); - } - v8SetReturnValue(info, promise); - return; -} - -void V8Promise::thenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Function> onFulfilled, onRejected; - if (info.Length() > 0 && info[0]->IsFunction()) - onFulfilled = info[0].As<v8::Function>(); - if (info.Length() > 1 && info[1]->IsFunction()) - onRejected = info[1].As<v8::Function>(); - v8SetReturnValue(info, V8PromiseCustom::then(info.Holder(), onFulfilled, onRejected, isolate)); -} - -void V8Promise::castMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Value> result = v8::Undefined(isolate); - if (info.Length() > 0) - result = info[0]; - - v8SetReturnValue(info, V8PromiseCustom::toPromise(result, isolate)); -} - -void V8Promise::catchMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Function> onFulfilled, onRejected; - - if (info.Length() > 0 && !info[0]->IsUndefined()) { - if (!info[0]->IsFunction()) { - v8SetReturnValue(info, throwTypeError("onRejected must be a function or undefined", isolate)); - return; - } - onRejected = info[0].As<v8::Function>(); - } - v8SetReturnValue(info, V8PromiseCustom::then(info.Holder(), onFulfilled, onRejected, isolate)); -} - -void V8Promise::resolveMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Value> result = v8::Undefined(isolate); - if (info.Length() > 0) - result = info[0]; - - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate); - V8PromiseCustom::resolve(promise, result, isolate); - v8SetReturnValue(info, promise); -} - -void V8Promise::rejectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Value> result = v8::Undefined(isolate); - if (info.Length() > 0) - result = info[0]; - - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate); - V8PromiseCustom::reject(promise, result, isolate); - v8SetReturnValue(info, promise); -} - -void V8Promise::raceMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate); - - if (!info.Length() || !info[0]->IsArray()) { - v8SetReturnValue(info, promise); - return; - } - - // FIXME: Now we limit the iterable type to the Array type. - v8::Local<v8::Array> iterable = info[0].As<v8::Array>(); - v8::Local<v8::Function> onFulfilled = createClosure(promiseResolveCallback, promise, isolate); - v8::Local<v8::Function> onRejected = createClosure(promiseRejectCallback, promise, isolate); - - for (unsigned i = 0, length = iterable->Length(); i < length; ++i) { - // Array-holes should not be skipped by for-of iteration semantics. - V8TRYCATCH_VOID(v8::Local<v8::Value>, nextValue, iterable->Get(i)); - v8::Local<v8::Object> nextPromise = V8PromiseCustom::toPromise(nextValue, isolate); - V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate); - } - v8SetReturnValue(info, promise); -} - -void V8Promise::allMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate); - v8::Local<v8::Array> results = v8::Array::New(info.GetIsolate()); - - if (!info.Length() || !info[0]->IsArray()) { - V8PromiseCustom::resolve(promise, results, isolate); - v8SetReturnValue(info, promise); - return; - } - - // FIXME: Now we limit the iterable type to the Array type. - v8::Local<v8::Array> iterable = info[0].As<v8::Array>(); - - if (!iterable->Length()) { - V8PromiseCustom::resolve(promise, results, isolate); - v8SetReturnValue(info, promise); - return; - } - - v8::Local<v8::ObjectTemplate> objectTemplate = primitiveWrapperObjectTemplate(isolate); - v8::Local<v8::Object> countdownWrapper = objectTemplate->NewInstance(); - countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex, v8::Integer::New(iterable->Length(), isolate)); - - v8::Local<v8::Function> onRejected = createClosure(promiseRejectCallback, promise, isolate); - for (unsigned i = 0, length = iterable->Length(); i < length; ++i) { - // Array-holes should not be skipped by for-of iteration semantics. - v8::Local<v8::Object> environment = promiseAllEnvironment(promise, countdownWrapper, i, results, isolate); - v8::Local<v8::Function> onFulfilled = createClosure(promiseAllFulfillCallback, environment, isolate); - V8TRYCATCH_VOID(v8::Local<v8::Value>, nextValue, iterable->Get(i)); - v8::Local<v8::Object> nextPromise = V8PromiseCustom::toPromise(nextValue, isolate); - V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate); - } - v8SetReturnValue(info, promise); -} - -// -// -- V8PromiseCustom -- -v8::Local<v8::Object> V8PromiseCustom::createPromise(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - v8::Local<v8::ObjectTemplate> internalTemplate = internalObjectTemplate(isolate); - v8::Local<v8::Object> internal = internalTemplate->NewInstance(); - v8::Local<v8::Object> promise = V8DOMWrapper::createWrapper(creationContext, &V8Promise::wrapperTypeInfo, 0, isolate); - - clearDerived(internal, isolate); - setState(internal, Pending, v8::Undefined(isolate), isolate); - - promise->SetInternalField(v8DOMWrapperObjectIndex, internal); - return promise; -} - -v8::Local<v8::Object> V8PromiseCustom::getInternal(v8::Handle<v8::Object> promise) -{ - v8::Local<v8::Value> value = promise->GetInternalField(v8DOMWrapperObjectIndex); - return value.As<v8::Object>(); -} - -V8PromiseCustom::PromiseState V8PromiseCustom::getState(v8::Handle<v8::Object> internal) -{ - v8::Handle<v8::Value> value = internal->GetInternalField(V8PromiseCustom::InternalStateIndex); - bool ok = false; - uint32_t number = toInt32(value, ok); - ASSERT(ok && (number == Pending || number == Fulfilled || number == Rejected || number == Following)); - return static_cast<PromiseState>(number); -} - -void V8PromiseCustom::setState(v8::Handle<v8::Object> internal, PromiseState state, v8::Handle<v8::Value> value, v8::Isolate* isolate) -{ - ASSERT(!value.IsEmpty()); - ASSERT(state == Pending || state == Fulfilled || state == Rejected || state == Following); - internal->SetInternalField(InternalStateIndex, v8::Integer::New(state, isolate)); - internal->SetInternalField(InternalResultIndex, value); -} - -bool V8PromiseCustom::isPromise(v8::Handle<v8::Value> maybePromise, v8::Isolate* isolate) -{ - WrapperWorldType currentWorldType = worldType(isolate); - return V8Promise::domTemplate(isolate, currentWorldType)->HasInstance(maybePromise); -} - -v8::Local<v8::Object> V8PromiseCustom::toPromise(v8::Handle<v8::Value> maybePromise, v8::Isolate* isolate) -{ - // FIXME: Currently we don't check [[PromiseConstructor]] since we limit - // the creation of the promise objects only from the Blink Promise - // constructor. - if (isPromise(maybePromise, isolate)) - return maybePromise.As<v8::Object>(); - - v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isolate); - resolve(promise, maybePromise, isolate); - return promise; -} - -void V8PromiseCustom::resolve(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> result, v8::Isolate* isolate) -{ - ASSERT(!result.IsEmpty()); - v8::Local<v8::Object> internal = getInternal(promise); - PromiseState state = getState(internal); - if (state != Pending) - return; - - if (isPromise(result, isolate)) { - v8::Local<v8::Object> valuePromise = result.As<v8::Object>(); - v8::Local<v8::Object> valueInternal = getInternal(valuePromise); - PromiseState valueState = getState(valueInternal); - if (promise->SameValue(valuePromise)) { - v8::Local<v8::Value> reason = V8ThrowException::createTypeError("Resolve a promise with itself", isolate); - setReason(promise, reason, isolate); - } else if (valueState == Following) { - v8::Local<v8::Object> valuePromiseFollowing = valueInternal->GetInternalField(InternalResultIndex).As<v8::Object>(); - setState(internal, Following, valuePromiseFollowing, isolate); - addToDerived(getInternal(valuePromiseFollowing), promise, v8::Handle<v8::Function>(), v8::Handle<v8::Function>(), isolate); - } else if (valueState == Fulfilled) { - setValue(promise, valueInternal->GetInternalField(InternalResultIndex), isolate); - } else if (valueState == Rejected) { - setReason(promise, valueInternal->GetInternalField(InternalResultIndex), isolate); - } else { - ASSERT(valueState == Pending); - setState(internal, Following, valuePromise, isolate); - addToDerived(valueInternal, promise, v8::Handle<v8::Function>(), v8::Handle<v8::Function>(), isolate); - } - } else { - setValue(promise, result, isolate); - } -} - -void V8PromiseCustom::reject(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> reason, v8::Isolate* isolate) -{ - v8::Local<v8::Object> internal = getInternal(promise); - PromiseState state = getState(internal); - if (state != Pending) - return; - setReason(promise, reason, isolate); -} - -v8::Local<v8::Object> V8PromiseCustom::then(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Isolate* isolate) -{ - v8::Handle<v8::Object> internal = getInternal(promise); - while (getState(internal) == Following) { - promise = internal->GetInternalField(InternalResultIndex).As<v8::Object>(); - internal = getInternal(promise); - } - // FIXME: Currently we don't lookup "constructor" property since we limit - // the creation of the promise objects only from the Blink Promise - // constructor. - v8::Local<v8::Object> derivedPromise = createPromise(v8::Handle<v8::Object>(), isolate); - updateDerivedFromPromise(derivedPromise, onFulfilled, onRejected, promise, isolate); - return derivedPromise; -} - -void V8PromiseCustom::setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> value, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.setValue(promise, value, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::setReason(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> reason, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.setReason(promise, reason, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::propagateToDerived(v8::Handle<v8::Object> promise, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.propagateToDerived(promise, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::updateDerived(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.updateDerived(derivedPromise, onFulfilled, onRejected, originator, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::updateDerivedFromValue(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Value> value, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.updateDerivedFromValue(derivedPromise, onFulfilled, value, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::updateDerivedFromReason(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Value> reason, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.updateDerivedFromReason(derivedPromise, onRejected, reason, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::updateDerivedFromPromise(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> promise, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.updateDerivedFromPromise(derivedPromise, onFulfilled, onRejected, promise, isolate); - propagator.performPropagation(isolate); -} - -v8::Local<v8::Object> V8PromiseCustom::coerceThenable(v8::Handle<v8::Object> thenable, v8::Handle<v8::Function> then, v8::Isolate* isolate) -{ - ASSERT(!thenable.IsEmpty()); - ASSERT(!then.IsEmpty()); - v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isolate); - v8::Handle<v8::Value> argv[] = { - createClosure(promiseResolveCallback, promise, isolate), - createClosure(promiseRejectCallback, promise, isolate) - }; - v8::TryCatch trycatch; - if (V8ScriptRunner::callFunction(then, getExecutionContext(), thenable, WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) { - reject(promise, trycatch.Exception(), isolate); - } - thenable->SetHiddenValue(V8HiddenPropertyName::thenableHiddenPromise(isolate), promise); - return promise; -} - -void V8PromiseCustom::callHandler(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> handler, v8::Handle<v8::Value> argument, v8::Isolate* isolate) -{ - ExecutionContext* executionContext = getExecutionContext(); - ASSERT(executionContext && executionContext->isContextThread()); - executionContext->postTask(adoptPtr(new CallHandlerTask(promise, handler, argument, isolate, executionContext))); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.h deleted file mode 100644 index 1751c1e4ae3..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2013, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef V8PromiseCustom_h -#define V8PromiseCustom_h - -#include "bindings/v8/WrapperTypeInfo.h" - -#include <v8.h> - -namespace WebCore { - -class V8PromiseCustom { -public: - enum InternalFieldIndex { - InternalStateIndex, - InternalResultIndex, - InternalFulfillCallbackIndex, - InternalRejectCallbackIndex, - InternalDerivedPromiseIndex, - InternalFieldCount, // This entry must always be at the bottom. - }; - - enum PromiseAllEnvironmentFieldIndex { - PromiseAllEnvironmentPromiseIndex, - PromiseAllEnvironmentCountdownIndex, - PromiseAllEnvironmentIndexIndex, - PromiseAllEnvironmentResultsIndex, - PromiseAllEnvironmentFieldCount, // This entry must always be at the bottom. - }; - - enum PrimitiveWrapperFieldIndex { - PrimitiveWrapperPrimitiveIndex, - PrimitiveWrapperFieldCount, // This entry must always be at the bottom. - }; - - enum PromiseState { - Pending, - Fulfilled, - Rejected, - Following, - }; - - static v8::Local<v8::Object> createPromise(v8::Handle<v8::Object> creationContext, v8::Isolate*); - - // |promise| must be a Promise instance. - static v8::Local<v8::Object> getInternal(v8::Handle<v8::Object> promise); - - // |internal| must be a Promise internal object. - static PromiseState getState(v8::Handle<v8::Object> internal); - - // |internal| must be a Promise internal object. - // Set a |promise|'s state and result that correspond to the state. - static void setState(v8::Handle<v8::Object> internal, PromiseState, v8::Handle<v8::Value>, v8::Isolate*); - - // Return true if |maybePromise| is a Promise instance. - static bool isPromise(v8::Handle<v8::Value> maybePromise, v8::Isolate*); - - // Coerces |maybePromise| to a Promise instance. - static v8::Local<v8::Object> toPromise(v8::Handle<v8::Value> maybePromise, v8::Isolate*); - - // |promise| must be a Promise instance. - static void resolve(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> result, v8::Isolate*); - - // |promise| must be a Promise instance. - static void reject(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> result, v8::Isolate*); - - // |promise| must be a Promise instance. - // |onFulfilled| and |onRejected| can be an empty value respectively. - // Appends |onFulfilled| and/or |onRejected| handlers to |promise|. - static v8::Local<v8::Object> then(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Isolate*); - - // |promise| must be a Promise instance. - // Set a |promise|'s value and propagate it to derived promises. - static void setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Value>, v8::Isolate*); - - // |promise| must be a Promise instance. - // Set a |promise|'s failure reason and propagate it to derived promises. - static void setReason(v8::Handle<v8::Object> promise, v8::Handle<v8::Value>, v8::Isolate*); - - // |promise| must be a Promise instance. - // Propagate a |promise|'s value or reason to all of its derived promies. - static void propagateToDerived(v8::Handle<v8::Object> promise, v8::Isolate*); - - // |derivedPromise| and |originator| must be a Promise instance. - // |onFulfilled| and |onRejected| can be an empty value respectively. - // Propagate |originator|'s state to |derivedPromise|. - static void updateDerived(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate*); - - // |derivedPromise| must be a Promise instance. - // Propagate a value to |derivedPromise|. - static void updateDerivedFromValue(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Value>, v8::Isolate*); - - // |derivedPromise| must be a Promise instance. - // Propagate a failure reason to |derivedPromise|. - static void updateDerivedFromReason(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Value>, v8::Isolate*); - - // |derivedPromise| and |promise| must be a Promise instance. - // |onFulfilled| and |onRejected| can be an empty value respectively. - // Propagate |promise|'s state to |derivedPromise|. - static void updateDerivedFromPromise(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> promise, v8::Isolate*); - - // Returns a Promise instance that will be fulfilled or rejected by - // |thenable|'s result. - static v8::Local<v8::Object> coerceThenable(v8::Handle<v8::Object> thenable, v8::Handle<v8::Function> then, v8::Isolate*); - - // |promise| must be a Promise instance. - // Applies a transformation to an argument and use it to update derived - // promies. - static void callHandler(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> handler, v8::Handle<v8::Value> argument, v8::Isolate*); -}; - -} // namespace WebCore - -#endif // V8PromiseCustom_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp index 3c41cb7b9a6..a6fed441759 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp @@ -29,22 +29,28 @@ */ #include "config.h" -#include "V8SQLResultSetRowList.h" +#include "bindings/modules/v8/V8SQLResultSetRowList.h" +#include "bindings/v8/ExceptionMessages.h" +#include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" +#include "core/dom/ExceptionCode.h" #include "modules/webdatabase/SQLResultSetRowList.h" namespace WebCore { void V8SQLResultSetRowList::itemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "item", "SQLResultSetRowList", info.Holder(), info.GetIsolate()); if (!info.Length()) { - throwError(v8SyntaxError, "Item index is required.", info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, ExceptionMessages::notEnoughArguments(1, 0)); + exceptionState.throwIfNeeded(); return; } if (!info[0]->IsNumber()) { - throwTypeError("Item index must be a number.", info.GetIsolate()); + exceptionState.throwTypeError("The index provided is not a number."); + exceptionState.throwIfNeeded(); return; } @@ -52,11 +58,12 @@ void V8SQLResultSetRowList::itemMethodCustom(const v8::FunctionCallbackInfo<v8:: unsigned long index = info[0]->IntegerValue(); if (index >= rowList->length()) { - throwError(v8RangeError, "Item index is out of range.", info.GetIsolate()); + exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::indexExceedsMaximumBound<unsigned>("index", index, rowList->length())); + exceptionState.throwIfNeeded(); return; } - v8::Local<v8::Object> item = v8::Object::New(); + v8::Local<v8::Object> item = v8::Object::New(info.GetIsolate()); unsigned numColumns = rowList->columnNames().size(); unsigned valuesIndex = index * numColumns; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp index 9a314b5f666..45a764ce042 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp @@ -29,10 +29,11 @@ */ #include "config.h" -#include "V8SQLTransaction.h" +#include "bindings/modules/v8/V8SQLTransaction.h" -#include "V8SQLStatementCallback.h" -#include "V8SQLStatementErrorCallback.h" +#include "bindings/modules/v8/V8SQLStatementCallback.h" +#include "bindings/modules/v8/V8SQLStatementErrorCallback.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" #include "core/dom/ExceptionCode.h" @@ -46,69 +47,70 @@ namespace WebCore { void V8SQLTransaction::executeSqlMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "executeSql", "SQLTransaction", info.Holder(), info.GetIsolate()); if (!info.Length()) { - setDOMException(SyntaxError, info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, ExceptionMessages::notEnoughArguments(1, 0)); + exceptionState.throwIfNeeded(); return; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, statement, info[0]); + TOSTRING_VOID(V8StringResource<>, statement, info[0]); Vector<SQLValue> sqlValues; if (info.Length() > 1 && !isUndefinedOrNull(info[1])) { if (!info[1]->IsObject()) { - setDOMException(TypeMismatchError, info.GetIsolate()); + exceptionState.throwDOMException(TypeMismatchError, "The 'arguments' (2nd) argument provided is not an object."); + exceptionState.throwIfNeeded(); return; } uint32_t sqlArgsLength = 0; v8::Local<v8::Object> sqlArgsObject = info[1]->ToObject(); - V8TRYCATCH_VOID(v8::Local<v8::Value>, length, sqlArgsObject->Get(v8AtomicString(info.GetIsolate(), "length"))); + TONATIVE_VOID(v8::Local<v8::Value>, length, sqlArgsObject->Get(v8AtomicString(info.GetIsolate(), "length"))); if (isUndefinedOrNull(length)) sqlArgsLength = sqlArgsObject->GetPropertyNames()->Length(); else sqlArgsLength = length->Uint32Value(); - for (unsigned int i = 0; i < sqlArgsLength; ++i) { - v8::Handle<v8::Integer> key = v8::Integer::New(i, info.GetIsolate()); - V8TRYCATCH_VOID(v8::Local<v8::Value>, value, sqlArgsObject->Get(key)); + for (unsigned i = 0; i < sqlArgsLength; ++i) { + v8::Handle<v8::Integer> key = v8::Integer::New(info.GetIsolate(), i); + TONATIVE_VOID(v8::Local<v8::Value>, value, sqlArgsObject->Get(key)); if (value.IsEmpty() || value->IsNull()) sqlValues.append(SQLValue()); else if (value->IsNumber()) { - V8TRYCATCH_VOID(double, sqlValue, value->NumberValue()); + TONATIVE_VOID(double, sqlValue, value->NumberValue()); sqlValues.append(SQLValue(sqlValue)); } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, sqlValue, value); + TOSTRING_VOID(V8StringResource<>, sqlValue, value); sqlValues.append(SQLValue(sqlValue)); } } } SQLTransaction* transaction = V8SQLTransaction::toNative(info.Holder()); - - ExecutionContext* executionContext = getExecutionContext(); - OwnPtr<SQLStatementCallback> callback; if (info.Length() > 2 && !isUndefinedOrNull(info[2])) { if (!info[2]->IsFunction()) { - setDOMException(TypeMismatchError, info.GetIsolate()); + exceptionState.throwDOMException(TypeMismatchError, "The 'callback' (2nd) argument provided is not a function."); + exceptionState.throwIfNeeded(); return; } - callback = V8SQLStatementCallback::create(v8::Handle<v8::Function>::Cast(info[2]), executionContext); + callback = V8SQLStatementCallback::create(v8::Handle<v8::Function>::Cast(info[2]), ScriptState::current(info.GetIsolate())); } OwnPtr<SQLStatementErrorCallback> errorCallback; if (info.Length() > 3 && !isUndefinedOrNull(info[3])) { if (!info[3]->IsFunction()) { - setDOMException(TypeMismatchError, info.GetIsolate()); + exceptionState.throwDOMException(TypeMismatchError, "The 'errorCallback' (3rd) argument provided is not a function."); + exceptionState.throwIfNeeded(); return; } - errorCallback = V8SQLStatementErrorCallback::create(v8::Handle<v8::Function>::Cast(info[3]), executionContext); + errorCallback = V8SQLStatementErrorCallback::create(v8::Handle<v8::Function>::Cast(info[3]), ScriptState::current(info.GetIsolate())); } - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); transaction->executeSQL(statement, sqlValues, callback.release(), errorCallback.release(), exceptionState); exceptionState.throwIfNeeded(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp index eaffffa0ca5..9b24721fa41 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp @@ -29,9 +29,9 @@ */ #include "config.h" -#include "V8SQLTransactionSync.h" +#include "bindings/modules/v8/V8SQLTransactionSync.h" -#include "V8SQLResultSet.h" +#include "bindings/modules/v8/V8SQLResultSet.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" #include "core/dom/ExceptionCode.h" @@ -46,41 +46,44 @@ namespace WebCore { void V8SQLTransactionSync::executeSqlMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "executeSql", "SQLTransactionSync", info.Holder(), info.GetIsolate()); if (!info.Length()) { - setDOMException(SyntaxError, info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, ExceptionMessages::notEnoughArguments(1, 0)); + exceptionState.throwIfNeeded(); return; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, statement, info[0]); + TOSTRING_VOID(V8StringResource<>, statement, info[0]); Vector<SQLValue> sqlValues; if (info.Length() > 1 && !isUndefinedOrNull(info[1])) { if (!info[1]->IsObject()) { - setDOMException(TypeMismatchError, info.GetIsolate()); + exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "DOMString")); + exceptionState.throwIfNeeded(); return; } uint32_t sqlArgsLength = 0; v8::Local<v8::Object> sqlArgsObject = info[1]->ToObject(); - V8TRYCATCH_VOID(v8::Local<v8::Value>, length, sqlArgsObject->Get(v8AtomicString(info.GetIsolate(), "length"))); + TONATIVE_VOID(v8::Local<v8::Value>, length, sqlArgsObject->Get(v8AtomicString(info.GetIsolate(), "length"))); if (isUndefinedOrNull(length)) sqlArgsLength = sqlArgsObject->GetPropertyNames()->Length(); else sqlArgsLength = length->Uint32Value(); - for (unsigned int i = 0; i < sqlArgsLength; ++i) { - v8::Handle<v8::Integer> key = v8::Integer::New(i, info.GetIsolate()); - V8TRYCATCH_VOID(v8::Local<v8::Value>, value, sqlArgsObject->Get(key)); + for (unsigned i = 0; i < sqlArgsLength; ++i) { + v8::Handle<v8::Integer> key = v8::Integer::New(info.GetIsolate(), i); + TONATIVE_VOID(v8::Local<v8::Value>, value, sqlArgsObject->Get(key)); if (value.IsEmpty() || value->IsNull()) sqlValues.append(SQLValue()); else if (value->IsNumber()) { - V8TRYCATCH_VOID(double, sqlValue, value->NumberValue()); + TONATIVE_VOID(double, sqlValue, value->NumberValue()); sqlValues.append(SQLValue(sqlValue)); } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, sqlValue, value); + TOSTRING_VOID(V8StringResource<>, sqlValue, value); sqlValues.append(SQLValue(sqlValue)); } } @@ -88,7 +91,6 @@ void V8SQLTransactionSync::executeSqlMethodCustom(const v8::FunctionCallbackInfo SQLTransactionSync* transaction = V8SQLTransactionSync::toNative(info.Holder()); - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); v8::Handle<v8::Value> result = toV8(transaction->executeSQL(statement, sqlValues, exceptionState), info.Holder(), info.GetIsolate()); if (exceptionState.throwIfNeeded()) return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGElementCustom.cpp index c21247e4d9a..abe89461fad 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGElementCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGElementCustom.cpp @@ -29,9 +29,9 @@ */ #include "config.h" -#include "V8SVGElement.h" +#include "bindings/core/v8/V8SVGElement.h" -#include "V8SVGElementWrapperFactory.h" +#include "core/V8SVGElementWrapperFactory.h" // FIXME: should be bindings/core/v8 namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGLengthCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGLengthCustom.cpp deleted file mode 100644 index a5a1cfef55b..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGLengthCustom.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8SVGLength.h" - -#include "bindings/v8/ExceptionMessages.h" -#include "bindings/v8/ExceptionState.h" -#include "bindings/v8/V8Binding.h" -#include "core/dom/ExceptionCode.h" -#include "core/svg/SVGLengthContext.h" -#include "core/svg/properties/SVGPropertyTearOff.h" - -namespace WebCore { - -void V8SVGLength::valueAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) -{ - SVGPropertyTearOff<SVGLength>* wrapper = V8SVGLength::toNative(info.Holder()); - SVGLength& imp = wrapper->propertyReference(); - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); - SVGLengthContext lengthContext(wrapper->contextElement()); - float value = imp.value(lengthContext, exceptionState); - if (exceptionState.throwIfNeeded()) - return; - v8SetReturnValue(info, value); -} - -void V8SVGLength::valueAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - SVGPropertyTearOff<SVGLength>* wrapper = V8SVGLength::toNative(info.Holder()); - if (wrapper->isReadOnly()) { - setDOMException(NoModificationAllowedError, info.GetIsolate()); - return; - } - - if (!isUndefinedOrNull(value) && !value->IsNumber() && !value->IsBoolean()) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); - return; - } - - SVGLength& imp = wrapper->propertyReference(); - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); - SVGLengthContext lengthContext(wrapper->contextElement()); - imp.setValue(static_cast<float>(value->NumberValue()), lengthContext, exceptionState); - if (exceptionState.throwIfNeeded()) - return; - wrapper->commitChange(); -} - -void V8SVGLength::convertToSpecifiedUnitsMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - ExceptionState exceptionState(ExceptionState::ExecutionContext, "convertToSpecifiedUnits", "SVGLength", info.Holder(), info.GetIsolate()); - SVGPropertyTearOff<SVGLength>* wrapper = V8SVGLength::toNative(info.Holder()); - if (wrapper->isReadOnly()) { - exceptionState.throwDOMException(NoModificationAllowedError, "The length is read only."); - exceptionState.throwIfNeeded(); - return; - } - - if (info.Length() < 1) { - exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, info.Length())); - exceptionState.throwIfNeeded(); - return; - } - - SVGLength& imp = wrapper->propertyReference(); - V8TRYCATCH_VOID(int, unitType, toUInt32(info[0])); - SVGLengthContext lengthContext(wrapper->contextElement()); - imp.convertToSpecifiedUnits(unitType, lengthContext, exceptionState); - if (exceptionState.throwIfNeeded()) - return; - wrapper->commitChange(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGPathSegCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGPathSegCustom.cpp index 77bf679d4f8..8d159757c06 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGPathSegCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGPathSegCustom.cpp @@ -29,28 +29,28 @@ */ #include "config.h" -#include "V8SVGPathSeg.h" +#include "bindings/core/v8/V8SVGPathSeg.h" -#include "V8SVGPathSegArcAbs.h" -#include "V8SVGPathSegArcRel.h" -#include "V8SVGPathSegClosePath.h" -#include "V8SVGPathSegCurvetoCubicAbs.h" -#include "V8SVGPathSegCurvetoCubicRel.h" -#include "V8SVGPathSegCurvetoCubicSmoothAbs.h" -#include "V8SVGPathSegCurvetoCubicSmoothRel.h" -#include "V8SVGPathSegCurvetoQuadraticAbs.h" -#include "V8SVGPathSegCurvetoQuadraticRel.h" -#include "V8SVGPathSegCurvetoQuadraticSmoothAbs.h" -#include "V8SVGPathSegCurvetoQuadraticSmoothRel.h" -#include "V8SVGPathSegLinetoAbs.h" -#include "V8SVGPathSegLinetoHorizontalAbs.h" -#include "V8SVGPathSegLinetoHorizontalRel.h" -#include "V8SVGPathSegLinetoRel.h" -#include "V8SVGPathSegLinetoVerticalAbs.h" -#include "V8SVGPathSegLinetoVerticalRel.h" -#include "V8SVGPathSegMovetoAbs.h" -#include "V8SVGPathSegMovetoRel.h" -#include "V8Window.h" +#include "bindings/core/v8/V8SVGPathSegArcAbs.h" +#include "bindings/core/v8/V8SVGPathSegArcRel.h" +#include "bindings/core/v8/V8SVGPathSegClosePath.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoCubicAbs.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoCubicRel.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoCubicSmoothAbs.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoCubicSmoothRel.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoQuadraticAbs.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoQuadraticRel.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoQuadraticSmoothAbs.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoQuadraticSmoothRel.h" +#include "bindings/core/v8/V8SVGPathSegLinetoAbs.h" +#include "bindings/core/v8/V8SVGPathSegLinetoHorizontalAbs.h" +#include "bindings/core/v8/V8SVGPathSegLinetoHorizontalRel.h" +#include "bindings/core/v8/V8SVGPathSegLinetoRel.h" +#include "bindings/core/v8/V8SVGPathSegLinetoVerticalAbs.h" +#include "bindings/core/v8/V8SVGPathSegLinetoVerticalRel.h" +#include "bindings/core/v8/V8SVGPathSegMovetoAbs.h" +#include "bindings/core/v8/V8SVGPathSegMovetoRel.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/V8DOMWrapper.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ServiceWorkerCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ServiceWorkerCustom.cpp new file mode 100644 index 00000000000..21337b4f437 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ServiceWorkerCustom.cpp @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/modules/v8/V8ServiceWorker.h" + +#include "bindings/v8/ExceptionMessages.h" +#include "bindings/v8/ExceptionState.h" +#include "bindings/v8/SerializedScriptValue.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/MessagePort.h" +#include "modules/serviceworkers/ServiceWorker.h" +#include "wtf/ArrayBuffer.h" + +namespace WebCore { + +void V8ServiceWorker::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "ServiceWorker", info.Holder(), info.GetIsolate()); + ServiceWorker* worker = V8ServiceWorker::toNative(info.Holder()); + MessagePortArray ports; + ArrayBufferArray arrayBuffers; + if (info.Length() > 1) { + const int transferablesArgIndex = 1; + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, ports, arrayBuffers, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); + return; + } + } + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) + return; + worker->postMessage(message.release(), &ports, exceptionState); + exceptionState.throwIfNeeded(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8StyleSheetCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8StyleSheetCustom.cpp index 39d28a800c6..8705d0783be 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8StyleSheetCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8StyleSheetCustom.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8StyleSheet.h" +#include "bindings/core/v8/V8StyleSheet.h" -#include "V8CSSStyleSheet.h" -#include "V8Node.h" +#include "bindings/core/v8/V8CSSStyleSheet.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/V8DOMWrapper.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SubtleCryptoCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SubtleCryptoCustom.cpp new file mode 100644 index 00000000000..943ad7666a0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SubtleCryptoCustom.cpp @@ -0,0 +1,125 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/modules/v8/V8SubtleCrypto.h" + +#include "bindings/modules/v8/V8Key.h" +#include "bindings/v8/Dictionary.h" +#include "bindings/v8/custom/V8ArrayBufferCustom.h" +#include "bindings/v8/custom/V8ArrayBufferViewCustom.h" + +namespace WebCore { + +//////////////////////////////////////////////////////////////////////////////// +// Overload resolution for verify() +// FIXME: needs support for union types http://crbug.com/240176 +//////////////////////////////////////////////////////////////////////////////// + +// Promise verify(Dictionary algorithm, Key key, ArrayBuffer signature, ArrayBuffer data); +void verify1Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + SubtleCrypto* impl = V8SubtleCrypto::toNative(info.Holder()); + TONATIVE_VOID(Dictionary, algorithm, Dictionary(info[0], info.GetIsolate())); + if (!algorithm.isUndefinedOrNull() && !algorithm.isObject()) { + throwTypeError(ExceptionMessages::failedToExecute("verify", "SubtleCrypto", "parameter 1 ('algorithm') is not an object."), info.GetIsolate()); + return; + } + TONATIVE_VOID(Key*, key, V8Key::toNativeWithTypeCheck(info.GetIsolate(), info[1])); + TONATIVE_VOID(ArrayBuffer*, signature, info[2]->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle<v8::ArrayBuffer>::Cast(info[2])) : 0); + TONATIVE_VOID(ArrayBuffer*, data, info[3]->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle<v8::ArrayBuffer>::Cast(info[3])) : 0); + v8SetReturnValue(info, impl->verifySignature(ScriptState::current(info.GetIsolate()), algorithm, key, signature, data).v8Value()); +} + +// Promise verify(Dictionary algorithm, Key key, ArrayBuffer signature, ArrayBufferView data); +void verify2Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + SubtleCrypto* impl = V8SubtleCrypto::toNative(info.Holder()); + TONATIVE_VOID(Dictionary, algorithm, Dictionary(info[0], info.GetIsolate())); + if (!algorithm.isUndefinedOrNull() && !algorithm.isObject()) { + throwTypeError(ExceptionMessages::failedToExecute("verify", "SubtleCrypto", "parameter 1 ('algorithm') is not an object."), info.GetIsolate()); + return; + } + TONATIVE_VOID(Key*, key, V8Key::toNativeWithTypeCheck(info.GetIsolate(), info[1])); + TONATIVE_VOID(ArrayBuffer*, signature, info[2]->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle<v8::ArrayBuffer>::Cast(info[2])) : 0); + TONATIVE_VOID(ArrayBufferView*, data, info[3]->IsArrayBufferView() ? V8ArrayBufferView::toNative(v8::Handle<v8::ArrayBufferView>::Cast(info[3])) : 0); + v8SetReturnValue(info, impl->verifySignature(ScriptState::current(info.GetIsolate()), algorithm, key, signature, data).v8Value()); +} + +// Promise verify(Dictionary algorithm, Key key, ArrayBufferView signature, ArrayBuffer data); +void verify3Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + SubtleCrypto* impl = V8SubtleCrypto::toNative(info.Holder()); + TONATIVE_VOID(Dictionary, algorithm, Dictionary(info[0], info.GetIsolate())); + if (!algorithm.isUndefinedOrNull() && !algorithm.isObject()) { + throwTypeError(ExceptionMessages::failedToExecute("verify", "SubtleCrypto", "parameter 1 ('algorithm') is not an object."), info.GetIsolate()); + return; + } + TONATIVE_VOID(Key*, key, V8Key::toNativeWithTypeCheck(info.GetIsolate(), info[1])); + TONATIVE_VOID(ArrayBufferView*, signature, info[2]->IsArrayBufferView() ? V8ArrayBufferView::toNative(v8::Handle<v8::ArrayBufferView>::Cast(info[2])) : 0); + TONATIVE_VOID(ArrayBuffer*, data, info[3]->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle<v8::ArrayBuffer>::Cast(info[3])) : 0); + v8SetReturnValue(info, impl->verifySignature(ScriptState::current(info.GetIsolate()), algorithm, key, signature, data).v8Value()); +} + +// Promise verify(Dictionary algorithm, Key key, ArrayBufferView signature, ArrayBufferView data); +void verify4Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + SubtleCrypto* impl = V8SubtleCrypto::toNative(info.Holder()); + TONATIVE_VOID(Dictionary, algorithm, Dictionary(info[0], info.GetIsolate())); + if (!algorithm.isUndefinedOrNull() && !algorithm.isObject()) { + throwTypeError(ExceptionMessages::failedToExecute("verify", "SubtleCrypto", "parameter 1 ('algorithm') is not an object."), info.GetIsolate()); + return; + } + TONATIVE_VOID(Key*, key, V8Key::toNativeWithTypeCheck(info.GetIsolate(), info[1])); + TONATIVE_VOID(ArrayBufferView*, signature, info[2]->IsArrayBufferView() ? V8ArrayBufferView::toNative(v8::Handle<v8::ArrayBufferView>::Cast(info[2])) : 0); + TONATIVE_VOID(ArrayBufferView*, data, info[3]->IsArrayBufferView() ? V8ArrayBufferView::toNative(v8::Handle<v8::ArrayBufferView>::Cast(info[3])) : 0); + v8SetReturnValue(info, impl->verifySignature(ScriptState::current(info.GetIsolate()), algorithm, key, signature, data).v8Value()); +} + +void V8SubtleCrypto::verifyMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + v8::Isolate* isolate = info.GetIsolate(); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "verify", "SubtleCrypto", info.Holder(), isolate); + // typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData; + // + // Promise verify(Dictionary algorithm, Key key, + // CryptoOperationData signature, + // CryptoOperationData data); + switch (info.Length()) { + case 4: + // Promise verify(Dictionary algorithm, Key key, ArrayBuffer signature, ArrayBuffer data); + if (V8ArrayBuffer::hasInstance(info[2], isolate) + && V8ArrayBuffer::hasInstance(info[3], isolate)) { + verify1Method(info); + return; + } + // Promise verify(Dictionary algorithm, Key key, ArrayBuffer signature, ArrayBufferView data); + if (V8ArrayBuffer::hasInstance(info[2], isolate) + && V8ArrayBufferView::hasInstance(info[3], isolate)) { + verify2Method(info); + return; + } + // Promise verify(Dictionary algorithm, Key key, ArrayBufferView signature, ArrayBuffer data); + if (V8ArrayBufferView::hasInstance(info[2], isolate) + && V8ArrayBuffer::hasInstance(info[3], isolate)) { + verify3Method(info); + return; + } + // Promise verify(Dictionary algorithm, Key key, ArrayBufferView signature, ArrayBufferView data); + if (V8ArrayBufferView::hasInstance(info[2], isolate) + && V8ArrayBufferView::hasInstance(info[3], isolate)) { + verify4Method(info); + return; + } + break; + default: + throwArityTypeError(exceptionState, "[4]", info.Length()); + return; + break; + } + exceptionState.throwTypeError("No function was found that matched the signature provided."); + exceptionState.throwIfNeeded(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextCustom.cpp index 478537c3b9f..4ffbadc0d3d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextCustom.cpp @@ -29,9 +29,9 @@ */ #include "config.h" -#include "V8Text.h" +#include "bindings/core/v8/V8Text.h" -#include "V8CDATASection.h" +#include "bindings/core/v8/V8CDATASection.h" #include "core/dom/Node.h" #include "core/dom/Text.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextTrackCueCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextTrackCueCustom.cpp index 3adef38297e..8d078eb91e9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextTrackCueCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextTrackCueCustom.cpp @@ -28,13 +28,9 @@ */ #include "config.h" -#include "V8TextTrackCue.h" +#include "bindings/core/v8/V8TextTrackCue.h" -#include "V8VTTCue.h" - -#include "bindings/v8/ExceptionMessages.h" -#include "bindings/v8/ExceptionState.h" -#include "core/frame/UseCounter.h" +#include "bindings/core/v8/V8VTTCue.h" namespace WebCore { @@ -43,27 +39,4 @@ v8::Handle<v8::Value> toV8(TextTrackCue* impl, v8::Handle<v8::Object> creationCo return toV8(toVTTCue(impl), creationContext, isolate); } -// Custom constructor to make new TextTrackCue(...) return a VTTCue. This is legacy -// compat, not per spec, and should be removed at the earliest opportunity. -void V8TextTrackCue::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - ExceptionState exceptionState(ExceptionState::ConstructionContext, "TextTrackCue", info.Holder(), info.GetIsolate()); - if (UNLIKELY(info.Length() < 3)) { - exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(3, info.Length())); - exceptionState.throwIfNeeded(); - return; - } - V8TRYCATCH_VOID(double, startTime, static_cast<double>(info[0]->NumberValue())); - V8TRYCATCH_VOID(double, endTime, static_cast<double>(info[1]->NumberValue())); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, text, info[2]); - - Document& document = *toDocument(getExecutionContext()); - UseCounter::count(document, UseCounter::TextTrackCueConstructor); - - RefPtr<VTTCue> impl = VTTCue::create(document, startTime, endTime, text); - v8::Handle<v8::Object> wrapper = wrap(impl.get(), info.Holder(), info.GetIsolate()); - - v8SetReturnValue(info, wrapper); -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TrackEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TrackEventCustom.cpp index aa76cc2c3fd..9c2b04e3c31 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TrackEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TrackEventCustom.cpp @@ -29,9 +29,11 @@ */ #include "config.h" -#include "V8TrackEvent.h" +#include "bindings/core/v8/V8TrackEvent.h" -#include "V8TextTrack.h" +#include "bindings/core/v8/V8AudioTrack.h" +#include "bindings/core/v8/V8TextTrack.h" +#include "bindings/core/v8/V8VideoTrack.h" #include "core/html/track/TrackBase.h" #include "core/html/track/TrackEvent.h" @@ -53,10 +55,12 @@ void V8TrackEvent::trackAttributeGetterCustom(const v8::PropertyCallbackInfo<v8: return; case TrackBase::AudioTrack: + v8SetReturnValueFast(info, static_cast<AudioTrack*>(track), trackEvent); + return; + case TrackBase::VideoTrack: - // This should not happen until VideoTrack and AudioTrack are implemented. - ASSERT_NOT_REACHED(); - break; + v8SetReturnValueFast(info, static_cast<VideoTrack*>(track), trackEvent); + return; } v8SetReturnValueNull(info); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TypedArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TypedArrayCustom.h index f64f457f2f5..fac7a110e5e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TypedArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TypedArrayCustom.h @@ -47,17 +47,13 @@ class TypedArrayTraits template<typename TypedArray> class V8TypedArray { public: - static bool hasInstance(v8::Handle<v8::Value> value, v8::Isolate*, WrapperWorldType) - { - return TypedArrayTraits<TypedArray>::IsInstance(value); - } - - static bool hasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isolate*) + static bool hasInstance(v8::Handle<v8::Value> value, v8::Isolate*) { return TypedArrayTraits<TypedArray>::IsInstance(value); } static TypedArray* toNative(v8::Handle<v8::Object>); + static TypedArray* toNativeWithTypeCheck(v8::Isolate*, v8::Handle<v8::Value>); static void derefObject(void*); static const WrapperTypeInfo wrapperTypeInfo; static const int internalFieldCount = v8DefaultWrapperInternalFieldCount; @@ -95,7 +91,7 @@ public: template<typename CallbackInfo> static void v8SetReturnValueForMainWorld(const CallbackInfo& info, TypedArray* impl) { - ASSERT(worldType(info.GetIsolate()) == MainWorld); + ASSERT(DOMWrapperWorld::current(info.GetIsolate()).isMainWorld()); if (UNLIKELY(!impl)) { v8SetReturnValueNull(info); return; @@ -174,12 +170,17 @@ TypedArray* V8TypedArray<TypedArray>::toNative(v8::Handle<v8::Object> object) return reinterpret_cast<TypedArray*>(typedarrayPtr); } +template <typename TypedArray> +TypedArray* V8TypedArray<TypedArray>::toNativeWithTypeCheck(v8::Isolate* isolate, v8::Handle<v8::Value> value) +{ + return V8TypedArray<TypedArray>::hasInstance(value, isolate) ? V8TypedArray<TypedArray>::toNative(v8::Handle<v8::Object>::Cast(value)) : 0; +} template <typename TypedArray> const WrapperTypeInfo V8TypedArray<TypedArray>::wrapperTypeInfo = { gin::kEmbedderBlink, 0, V8TypedArray<TypedArray>::derefObject, - 0, 0, 0, 0, 0, WrapperTypeObjectPrototype + 0, 0, 0, 0, 0, WrapperTypeObjectPrototype, RefCountedObject }; template <typename TypedArray> diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint16ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint16ArrayCustom.h index e692a9cb979..d819d228ece 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint16ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint16ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Uint16Array> V8Uint16Array; -template<> -class WrapperTypeTraits<Uint16Array> : public TypedArrayWrapperTraits<Uint16Array> { }; - - inline v8::Handle<v8::Object> wrap(Uint16Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Uint16Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint32ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint32ArrayCustom.h index 09ee5e990ec..9218135ef73 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint32ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint32ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Uint32Array> V8Uint32Array; -template<> -class WrapperTypeTraits<Uint32Array> : public TypedArrayWrapperTraits<Uint32Array> { }; - - inline v8::Handle<v8::Object> wrap(Uint32Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Uint32Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ArrayCustom.h index 5bcf0045731..7a37501dc64 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Uint8Array> V8Uint8Array; -template<> -class WrapperTypeTraits<Uint8Array> : public TypedArrayWrapperTraits<Uint8Array> { }; - - inline v8::Handle<v8::Object> wrap(Uint8Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Uint8Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ClampedArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ClampedArrayCustom.h index 53d938ad4d4..7f936669b8d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ClampedArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ClampedArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Uint8ClampedArray> V8Uint8ClampedArray; -template<> -class WrapperTypeTraits<Uint8ClampedArray> : public TypedArrayWrapperTraits<Uint8ClampedArray> { }; - - inline v8::Handle<v8::Object> wrap(Uint8ClampedArray* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Uint8ClampedArray>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp index 8eb86e9ba86..faa45a3ce42 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp @@ -29,41 +29,44 @@ */ #include "config.h" -#include "V8WebGLRenderingContext.h" - -#include "V8ANGLEInstancedArrays.h" -#include "V8EXTFragDepth.h" -#include "V8EXTTextureFilterAnisotropic.h" -#include "V8HTMLCanvasElement.h" -#include "V8HTMLImageElement.h" -#include "V8HTMLVideoElement.h" -#include "V8ImageData.h" -#include "V8OESElementIndexUint.h" -#include "V8OESStandardDerivatives.h" -#include "V8OESTextureFloat.h" -#include "V8OESTextureFloatLinear.h" -#include "V8OESTextureHalfFloat.h" -#include "V8OESTextureHalfFloatLinear.h" -#include "V8OESVertexArrayObject.h" -#include "V8WebGLBuffer.h" -#include "V8WebGLCompressedTextureATC.h" -#include "V8WebGLCompressedTexturePVRTC.h" -#include "V8WebGLCompressedTextureS3TC.h" -#include "V8WebGLDebugRendererInfo.h" -#include "V8WebGLDebugShaders.h" -#include "V8WebGLDepthTexture.h" -#include "V8WebGLDrawBuffers.h" -#include "V8WebGLFramebuffer.h" -#include "V8WebGLLoseContext.h" -#include "V8WebGLProgram.h" -#include "V8WebGLRenderbuffer.h" -#include "V8WebGLShader.h" -#include "V8WebGLTexture.h" -#include "V8WebGLUniformLocation.h" -#include "V8WebGLVertexArrayObjectOES.h" +#include "bindings/core/v8/V8WebGLRenderingContext.h" + +#include "bindings/core/v8/V8ANGLEInstancedArrays.h" +#include "bindings/core/v8/V8EXTBlendMinMax.h" +#include "bindings/core/v8/V8EXTFragDepth.h" +#include "bindings/core/v8/V8EXTShaderTextureLOD.h" +#include "bindings/core/v8/V8EXTTextureFilterAnisotropic.h" +#include "bindings/core/v8/V8HTMLCanvasElement.h" +#include "bindings/core/v8/V8HTMLImageElement.h" +#include "bindings/core/v8/V8HTMLVideoElement.h" +#include "bindings/core/v8/V8ImageData.h" +#include "bindings/core/v8/V8OESElementIndexUint.h" +#include "bindings/core/v8/V8OESStandardDerivatives.h" +#include "bindings/core/v8/V8OESTextureFloat.h" +#include "bindings/core/v8/V8OESTextureFloatLinear.h" +#include "bindings/core/v8/V8OESTextureHalfFloat.h" +#include "bindings/core/v8/V8OESTextureHalfFloatLinear.h" +#include "bindings/core/v8/V8OESVertexArrayObject.h" +#include "bindings/core/v8/V8WebGLBuffer.h" +#include "bindings/core/v8/V8WebGLCompressedTextureATC.h" +#include "bindings/core/v8/V8WebGLCompressedTextureETC1.h" +#include "bindings/core/v8/V8WebGLCompressedTexturePVRTC.h" +#include "bindings/core/v8/V8WebGLCompressedTextureS3TC.h" +#include "bindings/core/v8/V8WebGLDebugRendererInfo.h" +#include "bindings/core/v8/V8WebGLDebugShaders.h" +#include "bindings/core/v8/V8WebGLDepthTexture.h" +#include "bindings/core/v8/V8WebGLDrawBuffers.h" +#include "bindings/core/v8/V8WebGLFramebuffer.h" +#include "bindings/core/v8/V8WebGLLoseContext.h" +#include "bindings/core/v8/V8WebGLProgram.h" +#include "bindings/core/v8/V8WebGLRenderbuffer.h" +#include "bindings/core/v8/V8WebGLShader.h" +#include "bindings/core/v8/V8WebGLTexture.h" +#include "bindings/core/v8/V8WebGLUniformLocation.h" +#include "bindings/core/v8/V8WebGLVertexArrayObjectOES.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "bindings/v8/custom/V8Float32ArrayCustom.h" #include "bindings/v8/custom/V8Int16ArrayCustom.h" @@ -81,39 +84,43 @@ namespace WebCore { // Allocates new storage via fastMalloc. -// Returns NULL if array failed to convert for any reason. -static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len) +// Returns 0 if array failed to convert for any reason. +static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len, ExceptionState& exceptionState) { // Convert the data element-by-element. - if (len > std::numeric_limits<uint32_t>::max() / sizeof(float)) + if (len > std::numeric_limits<uint32_t>::max() / sizeof(float)) { + exceptionState.throwTypeError("Array length exceeds supported limit."); return 0; + } float* data = static_cast<float*>(fastMalloc(len * sizeof(float))); for (uint32_t i = 0; i < len; i++) { v8::Local<v8::Value> val = array->Get(i); - if (!val->IsNumber()) { + float value = toFloat(val, exceptionState); + if (exceptionState.hadException()) { fastFree(data); return 0; } - data[i] = toFloat(val); + data[i] = value; } return data; } // Allocates new storage via fastMalloc. -// Returns NULL if array failed to convert for any reason. -static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len) +// Returns 0 if array failed to convert for any reason. +static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len, ExceptionState& exceptionState) { // Convert the data element-by-element. - if (len > std::numeric_limits<uint32_t>::max() / sizeof(int)) + if (len > std::numeric_limits<uint32_t>::max() / sizeof(int)) { + exceptionState.throwTypeError("Array length exceeds supported limit."); return 0; + } int* data = static_cast<int*>(fastMalloc(len * sizeof(int))); for (uint32_t i = 0; i < len; i++) { v8::Local<v8::Value> val = array->Get(i); - bool ok; - int ival = toInt32(val, ok); - if (!ok) { + int ival = toInt32(val, exceptionState); + if (exceptionState.hadException()) { fastFree(data); return 0; } @@ -131,19 +138,19 @@ static v8::Handle<v8::Value> toV8Object(const WebGLGetInfo& args, v8::Handle<v8: const Vector<bool>& value = args.getBoolArray(); v8::Local<v8::Array> array = v8::Array::New(isolate, value.size()); for (size_t ii = 0; ii < value.size(); ++ii) - array->Set(v8::Integer::New(ii, isolate), v8Boolean(value[ii], isolate)); + array->Set(v8::Integer::New(isolate, ii), v8Boolean(value[ii], isolate)); return array; } case WebGLGetInfo::kTypeFloat: return v8::Number::New(isolate, args.getFloat()); case WebGLGetInfo::kTypeInt: - return v8::Integer::New(args.getInt(), isolate); + return v8::Integer::New(isolate, args.getInt()); case WebGLGetInfo::kTypeNull: return v8::Null(isolate); case WebGLGetInfo::kTypeString: return v8String(isolate, args.getString()); case WebGLGetInfo::kTypeUnsignedInt: - return v8::Integer::NewFromUnsigned(args.getUnsignedInt(), isolate); + return v8::Integer::NewFromUnsigned(isolate, args.getUnsignedInt()); case WebGLGetInfo::kTypeWebGLBuffer: return toV8(args.getWebGLBuffer(), creationContext, isolate); case WebGLGetInfo::kTypeWebGLFloatArray: @@ -179,81 +186,96 @@ static v8::Handle<v8::Value> toV8Object(WebGLExtension* extension, v8::Handle<v8 v8::Handle<v8::Value> extensionObject; const char* referenceName = 0; switch (extension->name()) { - case WebGLExtension::ANGLEInstancedArraysName: + case ANGLEInstancedArraysName: extensionObject = toV8(static_cast<ANGLEInstancedArrays*>(extension), contextObject, isolate); referenceName = "angleInstancedArraysName"; break; - case WebGLExtension::EXTFragDepthName: + case EXTBlendMinMaxName: + extensionObject = toV8(static_cast<EXTBlendMinMax*>(extension), contextObject, isolate); + referenceName = "extBlendMinMaxName"; + break; + case EXTFragDepthName: extensionObject = toV8(static_cast<EXTFragDepth*>(extension), contextObject, isolate); referenceName = "extFragDepthName"; break; - case WebGLExtension::EXTTextureFilterAnisotropicName: + case EXTShaderTextureLODName: + extensionObject = toV8(static_cast<EXTShaderTextureLOD*>(extension), contextObject, isolate); + referenceName = "extShaderTextureLODName"; + break; + case EXTTextureFilterAnisotropicName: extensionObject = toV8(static_cast<EXTTextureFilterAnisotropic*>(extension), contextObject, isolate); referenceName = "extTextureFilterAnisotropicName"; break; - case WebGLExtension::OESElementIndexUintName: + case OESElementIndexUintName: extensionObject = toV8(static_cast<OESElementIndexUint*>(extension), contextObject, isolate); referenceName = "oesElementIndexUintName"; break; - case WebGLExtension::OESStandardDerivativesName: + case OESStandardDerivativesName: extensionObject = toV8(static_cast<OESStandardDerivatives*>(extension), contextObject, isolate); referenceName = "oesStandardDerivativesName"; break; - case WebGLExtension::OESTextureFloatName: + case OESTextureFloatName: extensionObject = toV8(static_cast<OESTextureFloat*>(extension), contextObject, isolate); referenceName = "oesTextureFloatName"; break; - case WebGLExtension::OESTextureFloatLinearName: + case OESTextureFloatLinearName: extensionObject = toV8(static_cast<OESTextureFloatLinear*>(extension), contextObject, isolate); referenceName = "oesTextureFloatLinearName"; break; - case WebGLExtension::OESTextureHalfFloatName: + case OESTextureHalfFloatName: extensionObject = toV8(static_cast<OESTextureHalfFloat*>(extension), contextObject, isolate); referenceName = "oesTextureHalfFloatName"; break; - case WebGLExtension::OESTextureHalfFloatLinearName: + case OESTextureHalfFloatLinearName: extensionObject = toV8(static_cast<OESTextureHalfFloatLinear*>(extension), contextObject, isolate); referenceName = "oesTextureHalfFloatLinearName"; break; - case WebGLExtension::OESVertexArrayObjectName: + case OESVertexArrayObjectName: extensionObject = toV8(static_cast<OESVertexArrayObject*>(extension), contextObject, isolate); referenceName = "oesVertexArrayObjectName"; break; - case WebGLExtension::WebGLCompressedTextureATCName: + case WebGLCompressedTextureATCName: extensionObject = toV8(static_cast<WebGLCompressedTextureATC*>(extension), contextObject, isolate); referenceName = "webGLCompressedTextureATCName"; break; - case WebGLExtension::WebGLCompressedTexturePVRTCName: + case WebGLCompressedTextureETC1Name: + extensionObject = toV8(static_cast<WebGLCompressedTextureETC1*>(extension), contextObject, isolate); + referenceName = "webGLCompressedTextureETC1Name"; + break; + case WebGLCompressedTexturePVRTCName: extensionObject = toV8(static_cast<WebGLCompressedTexturePVRTC*>(extension), contextObject, isolate); referenceName = "webGLCompressedTexturePVRTCName"; break; - case WebGLExtension::WebGLCompressedTextureS3TCName: + case WebGLCompressedTextureS3TCName: extensionObject = toV8(static_cast<WebGLCompressedTextureS3TC*>(extension), contextObject, isolate); referenceName = "webGLCompressedTextureS3TCName"; break; - case WebGLExtension::WebGLDebugRendererInfoName: + case WebGLDebugRendererInfoName: extensionObject = toV8(static_cast<WebGLDebugRendererInfo*>(extension), contextObject, isolate); referenceName = "webGLDebugRendererInfoName"; break; - case WebGLExtension::WebGLDebugShadersName: + case WebGLDebugShadersName: extensionObject = toV8(static_cast<WebGLDebugShaders*>(extension), contextObject, isolate); referenceName = "webGLDebugShadersName"; break; - case WebGLExtension::WebGLDepthTextureName: + case WebGLDepthTextureName: extensionObject = toV8(static_cast<WebGLDepthTexture*>(extension), contextObject, isolate); referenceName = "webGLDepthTextureName"; break; - case WebGLExtension::WebGLDrawBuffersName: + case WebGLDrawBuffersName: extensionObject = toV8(static_cast<WebGLDrawBuffers*>(extension), contextObject, isolate); referenceName = "webGLDrawBuffersName"; break; - case WebGLExtension::WebGLLoseContextName: + case WebGLLoseContextName: extensionObject = toV8(static_cast<WebGLLoseContext*>(extension), contextObject, isolate); referenceName = "webGLLoseContextName"; break; + case WebGLExtensionNameCount: + notImplemented(); + return v8::Undefined(isolate); } ASSERT(!extensionObject.IsEmpty()); - V8HiddenPropertyName::setNamedHiddenReference(contextObject, referenceName, extensionObject); + V8HiddenValue::setHiddenValue(isolate, contextObject, v8AtomicString(isolate, referenceName), extensionObject); return extensionObject; } @@ -261,16 +283,21 @@ enum ObjectType { kBuffer, kRenderbuffer, kTexture, kVertexAttrib }; -static void getObjectParameter(const v8::FunctionCallbackInfo<v8::Value>& info, ObjectType objectType, const char* method) +static void getObjectParameter(const v8::FunctionCallbackInfo<v8::Value>& info, ObjectType objectType, ExceptionState& exceptionState) { if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - unsigned target = toInt32(info[0]); - unsigned pname = toInt32(info[1]); + unsigned target = toInt32(info[0], exceptionState); + if (exceptionState.throwIfNeeded()) + return; + unsigned pname = toInt32(info[1], exceptionState); + if (exceptionState.throwIfNeeded()) + return; WebGLGetInfo args; switch (objectType) { case kBuffer: @@ -293,15 +320,9 @@ static void getObjectParameter(const v8::FunctionCallbackInfo<v8::Value>& info, v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); } -static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, bool& ok, v8::Isolate* isolate) +static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, v8::Isolate* isolate) { - ok = false; - WebGLUniformLocation* location = 0; - if (V8WebGLUniformLocation::hasInstance(value, isolate, worldType(isolate))) { - location = V8WebGLUniformLocation::toNative(value->ToObject()); - ok = true; - } - return location; + return V8WebGLUniformLocation::toNativeWithTypeCheck(isolate, value); } enum WhichProgramCall { @@ -310,17 +331,21 @@ enum WhichProgramCall { void V8WebGLRenderingContext::getAttachedShadersMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getAttachedShaders", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() < 1) { - throwTypeError(ExceptionMessages::failedToExecute("getAttachedShaders", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(1, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, info.Length())); + exceptionState.throwIfNeeded(); return; } + const int programArgumentIndex = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info.Length() > 0 && !isUndefinedOrNull(info[programArgumentIndex]) && !V8WebGLProgram::hasInstance(info[programArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(programArgumentIndex + 1, "WebGLProgram")); + exceptionState.throwIfNeeded(); return; } - WebGLProgram* program = V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; + WebGLProgram* program = V8WebGLProgram::toNativeWithTypeCheck(info.GetIsolate(), info[programArgumentIndex]); Vector<RefPtr<WebGLShader> > shaders; bool succeed = context->getAttachedShaders(program, shaders); if (!succeed) { @@ -329,136 +354,169 @@ void V8WebGLRenderingContext::getAttachedShadersMethodCustom(const v8::FunctionC } v8::Local<v8::Array> array = v8::Array::New(info.GetIsolate(), shaders.size()); for (size_t ii = 0; ii < shaders.size(); ++ii) - array->Set(v8::Integer::New(ii, info.GetIsolate()), toV8(shaders[ii].get(), info.Holder(), info.GetIsolate())); + array->Set(v8::Integer::New(info.GetIsolate(), ii), toV8(shaders[ii].get(), info.Holder(), info.GetIsolate())); v8SetReturnValue(info, array); } void V8WebGLRenderingContext::getBufferParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - getObjectParameter(info, kBuffer, "getBufferParameter"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getBufferParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + getObjectParameter(info, kBuffer, exceptionState); } void V8WebGLRenderingContext::getExtensionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(info.Holder()); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getExtension", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + WebGLRenderingContext* impl = V8WebGLRenderingContext::toNative(info.Holder()); if (info.Length() < 1) { - throwTypeError(ExceptionMessages::failedToExecute("getExtension", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(1, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, info.Length())); + exceptionState.throwIfNeeded(); return; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, info[0]); - RefPtr<WebGLExtension> extension(imp->getExtension(name)); + TOSTRING_VOID(V8StringResource<>, name, info[0]); + RefPtr<WebGLExtension> extension(impl->getExtension(name)); v8SetReturnValue(info, toV8Object(extension.get(), info.Holder(), info.GetIsolate())); } void V8WebGLRenderingContext::getFramebufferAttachmentParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getFramebufferAttachmentParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() != 3) { - throwTypeError(ExceptionMessages::failedToExecute("getFramebufferAttachmentParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(3, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(3, info.Length())); + exceptionState.throwIfNeeded(); return; } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); unsigned target = toInt32(info[0]); - unsigned attachment = toInt32(info[1]); - unsigned pname = toInt32(info[2]); + unsigned attachment = toInt32(info[1], exceptionState); + if (exceptionState.throwIfNeeded()) + return; + unsigned pname = toInt32(info[2], exceptionState); + if (exceptionState.throwIfNeeded()) + return; WebGLGetInfo args = context->getFramebufferAttachmentParameter(target, attachment, pname); v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); } void V8WebGLRenderingContext::getParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() != 1) { - throwTypeError(ExceptionMessages::failedToExecute("getParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(1, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, info.Length())); + exceptionState.throwIfNeeded(); return; } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - unsigned pname = toInt32(info[0]); + unsigned pname = toInt32(info[0], exceptionState); + if (exceptionState.throwIfNeeded()) + return; WebGLGetInfo args = context->getParameter(pname); v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); } void V8WebGLRenderingContext::getProgramParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getProgramParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute("getProgramParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } + const int programArgumentIndex = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info.Length() > 0 && !isUndefinedOrNull(info[programArgumentIndex]) && !V8WebGLProgram::hasInstance(info[programArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(programArgumentIndex + 1, "WebGLProgram")); + exceptionState.throwIfNeeded(); return; } - WebGLProgram* program = V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - unsigned pname = toInt32(info[1]); + WebGLProgram* program = V8WebGLProgram::toNativeWithTypeCheck(info.GetIsolate(), info[programArgumentIndex]); + unsigned pname = toInt32(info[1], exceptionState); + if (exceptionState.throwIfNeeded()) + return; WebGLGetInfo args = context->getProgramParameter(program, pname); v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); } void V8WebGLRenderingContext::getRenderbufferParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - getObjectParameter(info, kRenderbuffer, "getRenderbufferParameter"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getRenderbufferParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + getObjectParameter(info, kRenderbuffer, exceptionState); } void V8WebGLRenderingContext::getShaderParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getShaderParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute("getShaderParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } + const int shaderArgumentIndex = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLShader::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info.Length() > 0 && !isUndefinedOrNull(info[shaderArgumentIndex]) && !V8WebGLShader::hasInstance(info[shaderArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(shaderArgumentIndex + 1, "WebGLShader")); + exceptionState.throwIfNeeded(); return; } - WebGLShader* shader = V8WebGLShader::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLShader::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - unsigned pname = toInt32(info[1]); + WebGLShader* shader = V8WebGLShader::toNativeWithTypeCheck(info.GetIsolate(), info[shaderArgumentIndex]); + unsigned pname = toInt32(info[1], exceptionState); + if (exceptionState.throwIfNeeded()) + return; WebGLGetInfo args = context->getShaderParameter(shader, pname); v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); } void V8WebGLRenderingContext::getSupportedExtensionsMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(info.Holder()); - if (imp->isContextLost()) { + WebGLRenderingContext* impl = V8WebGLRenderingContext::toNative(info.Holder()); + if (impl->isContextLost()) { v8SetReturnValueNull(info); return; } - Vector<String> value = imp->getSupportedExtensions(); + Vector<String> value = impl->getSupportedExtensions(); v8::Local<v8::Array> array = v8::Array::New(info.GetIsolate(), value.size()); for (size_t ii = 0; ii < value.size(); ++ii) - array->Set(v8::Integer::New(ii, info.GetIsolate()), v8String(info.GetIsolate(), value[ii])); + array->Set(v8::Integer::New(info.GetIsolate(), ii), v8String(info.GetIsolate(), value[ii])); v8SetReturnValue(info, array); } void V8WebGLRenderingContext::getTexParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - getObjectParameter(info, kTexture, "getTexParameter"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getTexParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + getObjectParameter(info, kTexture, exceptionState); } void V8WebGLRenderingContext::getUniformMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getUniform", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute("getUniform", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } + const int programArgumentIndex = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info.Length() > 0 && !isUndefinedOrNull(info[programArgumentIndex]) && !V8WebGLProgram::hasInstance(info[programArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(programArgumentIndex + 1, "WebGLProgram")); + exceptionState.throwIfNeeded(); return; } - WebGLProgram* program = V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; + WebGLProgram* program = V8WebGLProgram::toNativeWithTypeCheck(info.GetIsolate(), info[programArgumentIndex]); - if (info.Length() > 1 && !isUndefinedOrNull(info[1]) && !V8WebGLUniformLocation::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + const int uniformArgumentIndex = 1; + if (info.Length() > 1 && !isUndefinedOrNull(info[uniformArgumentIndex]) && !V8WebGLUniformLocation::hasInstance(info[uniformArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(uniformArgumentIndex + 1, "WebGLUniformLocation")); + exceptionState.throwIfNeeded(); return; } - bool ok = false; - WebGLUniformLocation* location = toWebGLUniformLocation(info[1], ok, info.GetIsolate()); + const int uniformLocationArgumentIndex = 1; + WebGLUniformLocation* location = toWebGLUniformLocation(info[uniformLocationArgumentIndex], info.GetIsolate()); WebGLGetInfo args = context->getUniform(program, location); v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); @@ -466,7 +524,8 @@ void V8WebGLRenderingContext::getUniformMethodCustom(const v8::FunctionCallbackI void V8WebGLRenderingContext::getVertexAttribMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - getObjectParameter(info, kVertexAttrib, "getVertexAttrib"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getVertexAttrib", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + getObjectParameter(info, kVertexAttrib, exceptionState); } enum FunctionToCall { @@ -488,7 +547,7 @@ bool isFunctionToCallForAttribute(FunctionToCall functionToCall) return false; } -static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Value>& info, FunctionToCall functionToCall, const char* method) +static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Value>& info, FunctionToCall functionToCall, ExceptionState& exceptionState) { // Forms: // * glUniform1fv(WebGLUniformLocation location, Array data); @@ -509,29 +568,34 @@ static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Val // * glVertexAttrib4fv(GLint index, Float32Array data); if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } - bool ok = false; int index = -1; WebGLUniformLocation* location = 0; - if (isFunctionToCallForAttribute(functionToCall)) - index = toInt32(info[0]); - else { - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLUniformLocation::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (isFunctionToCallForAttribute(functionToCall)) { + index = toInt32(info[0], exceptionState); + if (exceptionState.throwIfNeeded()) + return; + } else { + const int uniformLocationArgumentIndex = 0; + if (info.Length() > 0 && !isUndefinedOrNull(info[uniformLocationArgumentIndex]) && !V8WebGLUniformLocation::hasInstance(info[uniformLocationArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(uniformLocationArgumentIndex + 1, "WebGLUniformLocation")); + exceptionState.throwIfNeeded(); return; } - location = toWebGLUniformLocation(info[0], ok, info.GetIsolate()); + location = toWebGLUniformLocation(info[uniformLocationArgumentIndex], info.GetIsolate()); } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (V8Float32Array::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate()))) { - Float32Array* array = V8Float32Array::toNative(info[1]->ToObject()); - ASSERT(array != NULL); + const int indexArrayArgument = 1; + if (V8Float32Array::hasInstance(info[indexArrayArgument], info.GetIsolate())) { + Float32Array* array = V8Float32Array::toNative(info[indexArrayArgument]->ToObject()); + ASSERT(array); switch (functionToCall) { case kUniform1v: context->uniform1fv(location, array); break; case kUniform2v: context->uniform2fv(location, array); break; @@ -546,16 +610,20 @@ static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Val return; } - if (info[1].IsEmpty() || !info[1]->IsArray()) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info[indexArrayArgument].IsEmpty() || !info[indexArrayArgument]->IsArray()) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(indexArrayArgument + 1, "Array")); + exceptionState.throwIfNeeded(); return; } v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(info[1]); uint32_t len = array->Length(); - float* data = jsArrayToFloatArray(array, len); + float* data = jsArrayToFloatArray(array, len, exceptionState); + if (exceptionState.throwIfNeeded()) + return; if (!data) { // FIXME: consider different / better exception type. - setDOMException(SyntaxError, info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, "Failed to convert array argument"); + exceptionState.throwIfNeeded(); return; } switch (functionToCall) { @@ -572,7 +640,7 @@ static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Val fastFree(data); } -static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& info, FunctionToCall functionToCall, const char* method) +static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& info, FunctionToCall functionToCall, ExceptionState& exceptionState) { // Forms: // * glUniform1iv(GLUniformLocation location, Array data); @@ -585,21 +653,24 @@ static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& info, Func // * glUniform4iv(GLUniformLocation location, Int32Array data); if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } + const int uniformLocationArgumentIndex = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLUniformLocation::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info.Length() > 0 && !isUndefinedOrNull(info[uniformLocationArgumentIndex]) && !V8WebGLUniformLocation::hasInstance(info[uniformLocationArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(uniformLocationArgumentIndex + 1, "WebGLUniformLocation")); + exceptionState.throwIfNeeded(); return; } - bool ok = false; - WebGLUniformLocation* location = toWebGLUniformLocation(info[0], ok, info.GetIsolate()); + WebGLUniformLocation* location = toWebGLUniformLocation(info[uniformLocationArgumentIndex], info.GetIsolate()); - if (V8Int32Array::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate()))) { - Int32Array* array = V8Int32Array::toNative(info[1]->ToObject()); - ASSERT(array != NULL); + const int indexArrayArgumentIndex = 1; + if (V8Int32Array::hasInstance(info[indexArrayArgumentIndex], info.GetIsolate())) { + Int32Array* array = V8Int32Array::toNative(info[indexArrayArgumentIndex]->ToObject()); + ASSERT(array); switch (functionToCall) { case kUniform1v: context->uniform1iv(location, array); break; case kUniform2v: context->uniform2iv(location, array); break; @@ -610,16 +681,20 @@ static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& info, Func return; } - if (info[1].IsEmpty() || !info[1]->IsArray()) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info[indexArrayArgumentIndex].IsEmpty() || !info[indexArrayArgumentIndex]->IsArray()) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(indexArrayArgumentIndex + 1, "Array")); + exceptionState.throwIfNeeded(); return; } - v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(info[1]); + v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(info[indexArrayArgumentIndex]); uint32_t len = array->Length(); - int* data = jsArrayToIntArray(array, len); + int* data = jsArrayToIntArray(array, len, exceptionState); + if (exceptionState.throwIfNeeded()) + return; if (!data) { // FIXME: consider different / better exception type. - setDOMException(SyntaxError, info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, "Failed to convert array argument"); + exceptionState.throwIfNeeded(); return; } switch (functionToCall) { @@ -634,45 +709,53 @@ static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& info, Func void V8WebGLRenderingContext::uniform1fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kUniform1v, "uniform1fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform1fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kUniform1v, exceptionState); } void V8WebGLRenderingContext::uniform1ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformHelperi(info, kUniform1v, "uniform1iv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform1iv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformHelperi(info, kUniform1v, exceptionState); } void V8WebGLRenderingContext::uniform2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kUniform2v, "uniform2fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform2fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kUniform2v, exceptionState); } void V8WebGLRenderingContext::uniform2ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformHelperi(info, kUniform2v, "uniform2iv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform2iv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformHelperi(info, kUniform2v, exceptionState); } void V8WebGLRenderingContext::uniform3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kUniform3v, "uniform3fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform3fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kUniform3v, exceptionState); } void V8WebGLRenderingContext::uniform3ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformHelperi(info, kUniform3v, "uniform3iv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform3iv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformHelperi(info, kUniform3v, exceptionState); } void V8WebGLRenderingContext::uniform4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kUniform4v, "uniform4fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform4fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kUniform4v, exceptionState); } void V8WebGLRenderingContext::uniform4ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformHelperi(info, kUniform4v, "uniform4iv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform4iv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformHelperi(info, kUniform4v, exceptionState); } -static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& info, int matrixSize, const char* method) +static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& info, int matrixSize, ExceptionState& exceptionState) { // Forms: // * glUniformMatrix2fv(GLint location, GLboolean transpose, Array data); @@ -684,23 +767,26 @@ static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& info, // // FIXME: need to change to accept Float32Array as well. if (info.Length() != 3) { - throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(3, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(3, info.Length())); + exceptionState.throwIfNeeded(); return; } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLUniformLocation::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + const int uniformLocationArgumentIndex = 0; + if (info.Length() > 0 && !isUndefinedOrNull(info[uniformLocationArgumentIndex]) && !V8WebGLUniformLocation::hasInstance(info[uniformLocationArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(uniformLocationArgumentIndex + 1, "WebGLUniformLocation")); + exceptionState.throwIfNeeded(); return; } - bool ok = false; - WebGLUniformLocation* location = toWebGLUniformLocation(info[0], ok, info.GetIsolate()); + WebGLUniformLocation* location = toWebGLUniformLocation(info[uniformLocationArgumentIndex], info.GetIsolate()); bool transpose = info[1]->BooleanValue(); - if (V8Float32Array::hasInstance(info[2], info.GetIsolate(), worldType(info.GetIsolate()))) { - Float32Array* array = V8Float32Array::toNative(info[2]->ToObject()); - ASSERT(array != NULL); + const int arrayArgumentIndex = 2; + if (V8Float32Array::hasInstance(info[arrayArgumentIndex], info.GetIsolate())) { + Float32Array* array = V8Float32Array::toNative(info[arrayArgumentIndex]->ToObject()); + ASSERT(array); switch (matrixSize) { case 2: context->uniformMatrix2fv(location, transpose, array); break; case 3: context->uniformMatrix3fv(location, transpose, array); break; @@ -710,16 +796,20 @@ static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& info, return; } - if (info[2].IsEmpty() || !info[2]->IsArray()) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info[arrayArgumentIndex].IsEmpty() || !info[arrayArgumentIndex]->IsArray()) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(arrayArgumentIndex + 1, "Array")); + exceptionState.throwIfNeeded(); return; } v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(info[2]); uint32_t len = array->Length(); - float* data = jsArrayToFloatArray(array, len); + float* data = jsArrayToFloatArray(array, len, exceptionState); + if (exceptionState.throwIfNeeded()) + return; if (!data) { // FIXME: consider different / better exception type. - setDOMException(SyntaxError, info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, "failed to convert Array value"); + exceptionState.throwIfNeeded(); return; } switch (matrixSize) { @@ -733,37 +823,44 @@ static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& info, void V8WebGLRenderingContext::uniformMatrix2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformMatrixHelper(info, 2, "uniformMatrix2fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniformMatrix2fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformMatrixHelper(info, 2, exceptionState); } void V8WebGLRenderingContext::uniformMatrix3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformMatrixHelper(info, 3, "uniformMatrix3fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniformMatrix3fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformMatrixHelper(info, 3, exceptionState); } void V8WebGLRenderingContext::uniformMatrix4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformMatrixHelper(info, 4, "uniformMatrix4fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniformMatrix4fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformMatrixHelper(info, 4, exceptionState); } void V8WebGLRenderingContext::vertexAttrib1fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kVertexAttrib1v, "vertexAttrib1fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "vertexAttrib1fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kVertexAttrib1v, exceptionState); } void V8WebGLRenderingContext::vertexAttrib2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kVertexAttrib2v, "vertexAttrib2fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "vertexAttrib2fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kVertexAttrib2v, exceptionState); } void V8WebGLRenderingContext::vertexAttrib3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kVertexAttrib3v, "vertexAttrib3fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "vertexAttrib3fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kVertexAttrib3v, exceptionState); } void V8WebGLRenderingContext::vertexAttrib4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kVertexAttrib4v, "vertexAttrib4fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "vertexAttrib4fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kVertexAttrib4v, exceptionState); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebKitPointCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebKitPointCustom.cpp index 35429f91ffd..e87549ec81f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebKitPointCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebKitPointCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "V8WebKitPoint.h" +#include "bindings/core/v8/V8WebKitPoint.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" @@ -54,7 +54,7 @@ void V8WebKitPoint::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& y = 0; } } - RefPtr<DOMPoint> point = DOMPoint::create(x, y); + RefPtrWillBeRawPtr<DOMPoint> point = DOMPoint::create(x, y); v8::Handle<v8::Object> wrapper = info.Holder(); V8DOMWrapper::associateObjectWithWrapper<V8WebKitPoint>(point.release(), &wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); info.GetReturnValue().Set(wrapper); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WindowCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WindowCustom.cpp index 24f19e4fd10..7ab9e529d00 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WindowCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WindowCustom.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Window.h" -#include "V8HTMLCollection.h" -#include "V8Node.h" +#include "bindings/core/v8/V8HTMLCollection.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/BindingSecurity.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" @@ -44,8 +44,7 @@ #include "bindings/v8/V8EventListener.h" #include "bindings/v8/V8EventListenerList.h" #include "bindings/v8/V8GCForContextDispose.h" -#include "bindings/v8/V8HiddenPropertyName.h" -#include "bindings/v8/V8Utilities.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/ExceptionCode.h" #include "core/dom/MessagePort.h" #include "core/html/HTMLCollection.h" @@ -53,13 +52,13 @@ #include "core/inspector/ScriptCallStack.h" #include "core/loader/FrameLoadRequest.h" #include "core/loader/FrameLoader.h" -#include "core/frame/ContentSecurityPolicy.h" #include "core/frame/DOMTimer.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "core/frame/DOMWindowTimers.h" -#include "core/frame/Frame.h" #include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/storage/Storage.h" #include "platform/PlatformScreen.h" #include "platform/graphics/media/MediaPlayer.h" @@ -71,19 +70,19 @@ namespace WebCore { // FIXME: There is a lot of duplication with SetTimeoutOrInterval() in V8WorkerGlobalScopeCustom.cpp. // We should refactor this. -void WindowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool singleShot, ExceptionState& exceptionState) +static void windowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool singleShot, ExceptionState& exceptionState) { int argumentCount = info.Length(); if (argumentCount < 1) return; - DOMWindow* imp = V8Window::toNative(info.Holder()); - if (!imp->document()) { + LocalDOMWindow* impl = V8Window::toNative(info.Holder()); + if (!impl->frame() || !impl->document()) { exceptionState.throwDOMException(InvalidAccessError, "No script context is available in which to execute the script."); return; } - + ScriptState* scriptState = ScriptState::current(info.GetIsolate()); v8::Handle<v8::Value> function = info[0]; String functionString; if (!function->IsFunction()) { @@ -105,7 +104,7 @@ void WindowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool return; } - if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), exceptionState)) + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) return; OwnPtr<ScheduledAction> action; @@ -121,23 +120,23 @@ void WindowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool } // params is passed to action, and released in action's destructor - ASSERT(imp->frame()); - action = adoptPtr(new ScheduledAction(imp->frame()->script().currentWorldContext(), v8::Handle<v8::Function>::Cast(function), paramCount, params.get(), info.GetIsolate())); + ASSERT(impl->frame()); + action = adoptPtr(new ScheduledAction(scriptState, v8::Handle<v8::Function>::Cast(function), paramCount, params.get(), info.GetIsolate())); } else { - if (imp->document() && !imp->document()->contentSecurityPolicy()->allowEval()) { + if (impl->document() && !impl->document()->contentSecurityPolicy()->allowEval()) { v8SetReturnValue(info, 0); return; } - ASSERT(imp->frame()); - action = adoptPtr(new ScheduledAction(imp->frame()->script().currentWorldContext(), functionString, KURL(), info.GetIsolate())); + ASSERT(impl->frame()); + action = adoptPtr(new ScheduledAction(scriptState, functionString, KURL(), info.GetIsolate())); } int32_t timeout = argumentCount >= 2 ? info[1]->Int32Value() : 0; int timerId; if (singleShot) - timerId = DOMWindowTimers::setTimeout(imp, action.release(), timeout); + timerId = DOMWindowTimers::setTimeout(*impl, action.release(), timeout); else - timerId = DOMWindowTimers::setInterval(imp, action.release(), timeout); + timerId = DOMWindowTimers::setInterval(*impl, action.release(), timeout); // Try to do the idle notification before the timeout expires to get better // use of any idle time. Aim for the middle of the interval for simplicity. @@ -151,24 +150,14 @@ void WindowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool void V8Window::eventAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { - v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate()))); - if (holder.IsEmpty()) - return; - - Frame* frame = V8Window::toNative(holder)->frame(); + LocalFrame* frame = V8Window::toNative(info.Holder())->frame(); ExceptionState exceptionState(ExceptionState::GetterContext, "event", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(frame, exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), frame, exceptionState)) { exceptionState.throwIfNeeded(); return; } - ASSERT(frame); - v8::Local<v8::Context> context = frame->script().currentWorldContext(); - if (context.IsEmpty()) - return; - - v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(info.GetIsolate()); - v8::Handle<v8::Value> jsEvent = context->Global()->GetHiddenValue(eventSymbol); + v8::Handle<v8::Value> jsEvent = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder()->CreationContext()->Global(), V8HiddenValue::event(info.GetIsolate())); if (jsEvent.IsEmpty()) return; v8SetReturnValue(info, jsEvent); @@ -176,31 +165,21 @@ void V8Window::eventAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Val void V8Window::eventAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { - v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate()))); - if (holder.IsEmpty()) - return; - - Frame* frame = V8Window::toNative(holder)->frame(); + LocalFrame* frame = V8Window::toNative(info.Holder())->frame(); ExceptionState exceptionState(ExceptionState::SetterContext, "event", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(frame, exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), frame, exceptionState)) { exceptionState.throwIfNeeded(); return; } - ASSERT(frame); - v8::Local<v8::Context> context = frame->script().currentWorldContext(); - if (context.IsEmpty()) - return; - - v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(info.GetIsolate()); - context->Global()->SetHiddenValue(eventSymbol, value); + V8HiddenValue::setHiddenValue(info.GetIsolate(), info.Holder()->CreationContext()->Global(), V8HiddenValue::event(info.GetIsolate()), value); } void V8Window::frameElementAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { - DOMWindow* imp = V8Window::toNative(info.Holder()); + LocalDOMWindow* impl = V8Window::toNative(info.Holder()); ExceptionState exceptionState(ExceptionState::GetterContext, "frame", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToNode(imp->frameElement(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), impl->frameElement(), exceptionState)) { v8SetReturnValueNull(info); exceptionState.throwIfNeeded(); return; @@ -208,17 +187,17 @@ void V8Window::frameElementAttributeGetterCustom(const v8::PropertyCallbackInfo< // The wrapper for an <iframe> should get its prototype from the context of the frame it's in, rather than its own frame. // So, use its containing document as the creation context when wrapping. - v8::Handle<v8::Value> creationContext = toV8(&imp->frameElement()->document(), v8::Handle<v8::Object>(), info.GetIsolate()); + v8::Handle<v8::Value> creationContext = toV8(&impl->frameElement()->document(), info.Holder(), info.GetIsolate()); RELEASE_ASSERT(!creationContext.IsEmpty()); - v8::Handle<v8::Value> wrapper = toV8(imp->frameElement(), v8::Handle<v8::Object>::Cast(creationContext), info.GetIsolate()); + v8::Handle<v8::Value> wrapper = toV8(impl->frameElement(), v8::Handle<v8::Object>::Cast(creationContext), info.GetIsolate()); v8SetReturnValue(info, wrapper); } void V8Window::openerAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { - DOMWindow* imp = V8Window::toNative(info.Holder()); + LocalDOMWindow* impl = V8Window::toNative(info.Holder()); ExceptionState exceptionState(ExceptionState::SetterContext, "opener", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) { exceptionState.throwIfNeeded(); return; } @@ -227,17 +206,18 @@ void V8Window::openerAttributeSetterCustom(v8::Local<v8::Value> value, const v8: // Have a special handling of null value to behave // like Firefox. See bug http://b/1224887 & http://b/791706. if (value->IsNull()) { - // imp->frame() cannot be null, + // impl->frame() cannot be null, // otherwise, SameOrigin check would have failed. - ASSERT(imp->frame()); - imp->frame()->loader().setOpener(0); + ASSERT(impl->frame()); + impl->frame()->loader().setOpener(0); } // Delete the accessor from this object. info.Holder()->Delete(v8AtomicString(info.GetIsolate(), "opener")); // Put property on the front (this) object. - info.This()->Set(v8AtomicString(info.GetIsolate(), "opener"), value); + if (info.This()->IsObject()) + v8::Handle<v8::Object>::Cast(info.This())->Set(v8AtomicString(info.GetIsolate(), "opener"), value); } static bool isLegacyTargetOriginDesignation(v8::Handle<v8::Value> value) @@ -252,12 +232,15 @@ void V8Window::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value> { // None of these need to be RefPtr because info and context are guaranteed // to hold on to them. - DOMWindow* window = V8Window::toNative(info.Holder()); - DOMWindow* source = activeDOMWindow(); + LocalDOMWindow* window = V8Window::toNative(info.Holder()); + LocalDOMWindow* source = callingDOMWindow(info.GetIsolate()); + + ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "Window", info.Holder(), info.GetIsolate()); // If called directly by WebCore we don't have a calling context. if (!source) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + exceptionState.throwTypeError("No active calling context exists."); + exceptionState.throwIfNeeded(); return; } @@ -276,22 +259,17 @@ void V8Window::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value> targetOriginArgIndex = 2; transferablesArgIndex = 1; } - bool notASequence = false; - if (!extractTransferables(info[transferablesArgIndex], portArray, arrayBufferArray, notASequence, info.GetIsolate())) { - if (notASequence) - throwTypeError(ExceptionMessages::failedToExecute("postMessage", "Window", ExceptionMessages::notAnArrayTypeArgumentOrValue(transferablesArgIndex + 1)), info.GetIsolate()); + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, portArray, arrayBufferArray, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); return; } } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, targetOrigin, info[targetOriginArgIndex]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, targetOrigin, info[targetOriginArgIndex]); - bool didThrow = false; - RefPtr<SerializedScriptValue> message = - SerializedScriptValue::create(info[0], &portArray, &arrayBufferArray, didThrow, info.GetIsolate()); - if (didThrow) + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &portArray, &arrayBufferArray, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; - ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "Window", info.Holder(), info.GetIsolate()); window->postMessage(message.release(), &portArray, targetOrigin, source, exceptionState); exceptionState.throwIfNeeded(); } @@ -302,7 +280,7 @@ void V8Window::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value> // switching context of receiver. I consider it is dangerous. void V8Window::toStringMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - v8::Handle<v8::Object> domWrapper = info.This()->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate()))); + v8::Handle<v8::Object> domWrapper = V8Window::findInstanceInPrototypeChain(info.This(), info.GetIsolate()); if (domWrapper.IsEmpty()) { v8SetReturnValue(info, info.This()->ObjectProtoToString()); return; @@ -312,84 +290,92 @@ void V8Window::toStringMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& i class DialogHandler { public: - explicit DialogHandler(v8::Handle<v8::Value> dialogArguments) - : m_dialogArguments(dialogArguments) + explicit DialogHandler(v8::Handle<v8::Value> dialogArguments, ScriptState* scriptState) + : m_scriptState(scriptState) + , m_dialogArguments(dialogArguments) { } - void dialogCreated(DOMWindow*, v8::Isolate*); - v8::Handle<v8::Value> returnValue(v8::Isolate*) const; + void dialogCreated(LocalDOMWindow*); + v8::Handle<v8::Value> returnValue() const; private: + RefPtr<ScriptState> m_scriptState; + RefPtr<ScriptState> m_scriptStateForDialogFrame; v8::Handle<v8::Value> m_dialogArguments; - v8::Handle<v8::Context> m_dialogContext; }; -inline void DialogHandler::dialogCreated(DOMWindow* dialogFrame, v8::Isolate* isolate) +void DialogHandler::dialogCreated(LocalDOMWindow* dialogFrame) { - m_dialogContext = dialogFrame->frame() ? dialogFrame->frame()->script().currentWorldContext() : v8::Local<v8::Context>(); - if (m_dialogContext.IsEmpty()) - return; if (m_dialogArguments.IsEmpty()) return; - v8::Context::Scope scope(m_dialogContext); - m_dialogContext->Global()->Set(v8AtomicString(isolate, "dialogArguments"), m_dialogArguments); + v8::Handle<v8::Context> context = toV8Context(dialogFrame->frame(), m_scriptState->world()); + if (context.IsEmpty()) + return; + m_scriptStateForDialogFrame = ScriptState::from(context); + + ScriptState::Scope scope(m_scriptStateForDialogFrame.get()); + m_scriptStateForDialogFrame->context()->Global()->Set(v8AtomicString(m_scriptState->isolate(), "dialogArguments"), m_dialogArguments); } -inline v8::Handle<v8::Value> DialogHandler::returnValue(v8::Isolate* isolate) const +v8::Handle<v8::Value> DialogHandler::returnValue() const { - if (m_dialogContext.IsEmpty()) - return v8::Undefined(isolate); - v8::Context::Scope scope(m_dialogContext); - v8::Handle<v8::Value> returnValue = m_dialogContext->Global()->Get(v8AtomicString(isolate, "returnValue")); + if (!m_scriptStateForDialogFrame) + return v8Undefined(); + ASSERT(!m_scriptStateForDialogFrame->contextIsEmpty()); + + v8::Isolate* isolate = m_scriptStateForDialogFrame->isolate(); + v8::EscapableHandleScope handleScope(isolate); + ScriptState::Scope scope(m_scriptStateForDialogFrame.get()); + v8::Local<v8::Value> returnValue = m_scriptStateForDialogFrame->context()->Global()->Get(v8AtomicString(isolate, "returnValue")); if (returnValue.IsEmpty()) - return v8::Undefined(isolate); - return returnValue; + return v8Undefined(); + return handleScope.Escape(returnValue); } -static void setUpDialog(DOMWindow* dialog, void* handler) +static void setUpDialog(LocalDOMWindow* dialog, void* handler) { - static_cast<DialogHandler*>(handler)->dialogCreated(dialog, v8::Isolate::GetCurrent()); + static_cast<DialogHandler*>(handler)->dialogCreated(dialog); } void V8Window::showModalDialogMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - DOMWindow* impl = V8Window::toNative(info.Holder()); + LocalDOMWindow* impl = V8Window::toNative(info.Holder()); ExceptionState exceptionState(ExceptionState::ExecutionContext, "showModalDialog", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) { exceptionState.throwIfNeeded(); return; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]); - DialogHandler handler(info[1]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, dialogFeaturesString, info[2]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]); + DialogHandler handler(info[1], ScriptState::current(info.GetIsolate())); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, dialogFeaturesString, info[2]); - impl->showModalDialog(urlString, dialogFeaturesString, activeDOMWindow(), firstDOMWindow(), setUpDialog, &handler); + impl->showModalDialog(urlString, dialogFeaturesString, callingDOMWindow(info.GetIsolate()), enteredDOMWindow(info.GetIsolate()), setUpDialog, &handler); - v8SetReturnValue(info, handler.returnValue(info.GetIsolate())); + v8SetReturnValue(info, handler.returnValue()); } void V8Window::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - DOMWindow* impl = V8Window::toNative(info.Holder()); + LocalDOMWindow* impl = V8Window::toNative(info.Holder()); ExceptionState exceptionState(ExceptionState::ExecutionContext, "open", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) { exceptionState.throwIfNeeded(); return; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]); AtomicString frameName; if (info[1]->IsUndefined() || info[1]->IsNull()) { frameName = "_blank"; } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, frameNameResource, info[1]); + TOSTRING_VOID(V8StringResource<>, frameNameResource, info[1]); frameName = frameNameResource; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, windowFeaturesString, info[2]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, windowFeaturesString, info[2]); - RefPtr<DOMWindow> openedWindow = impl->open(urlString, frameName, windowFeaturesString, activeDOMWindow(), firstDOMWindow()); + RefPtrWillBeRawPtr<LocalDOMWindow> openedWindow = impl->open(urlString, frameName, windowFeaturesString, callingDOMWindow(info.GetIsolate()), enteredDOMWindow(info.GetIsolate())); if (!openedWindow) return; @@ -399,11 +385,11 @@ void V8Window::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) void V8Window::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info) { - DOMWindow* window = V8Window::toNative(info.Holder()); + LocalDOMWindow* window = V8Window::toNative(info.Holder()); if (!window) return; - Frame* frame = window->frame(); + LocalFrame* frame = window->frame(); // window is detached from a frame. if (!frame) return; @@ -425,7 +411,7 @@ void V8Window::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::P if (doc && doc->isHTMLDocument()) { if (toHTMLDocument(doc)->hasNamedItem(propName) || doc->hasElementWithId(propName.impl())) { - RefPtr<HTMLCollection> items = doc->windowNamedItems(propName); + RefPtrWillBeRawPtr<HTMLCollection> items = doc->windowNamedItems(propName); if (!items->isEmpty()) { if (items->hasExactlyOneItem()) { v8SetReturnValueFast(info, items->item(0), window); @@ -442,7 +428,7 @@ void V8Window::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::P void V8Window::setTimeoutMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ExecutionContext, "setTimeout", "Window", info.Holder(), info.GetIsolate()); - WindowSetTimeoutImpl(info, true, exceptionState); + windowSetTimeoutImpl(info, true, exceptionState); exceptionState.throwIfNeeded(); } @@ -450,22 +436,22 @@ void V8Window::setTimeoutMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& void V8Window::setIntervalMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ExecutionContext, "setInterval", "Window", info.Holder(), info.GetIsolate()); - WindowSetTimeoutImpl(info, false, exceptionState); + windowSetTimeoutImpl(info, false, exceptionState); exceptionState.throwIfNeeded(); } bool V8Window::namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::Handle<v8::Object> window = host->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldTypeInMainThread(isolate))); + v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(host, isolate); if (window.IsEmpty()) return false; // the frame is gone. - DOMWindow* targetWindow = V8Window::toNative(window); + LocalDOMWindow* targetWindow = V8Window::toNative(window); ASSERT(targetWindow); - Frame* target = targetWindow->frame(); + LocalFrame* target = targetWindow->frame(); if (!target) return false; @@ -494,21 +480,21 @@ bool V8Window::namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8 return true; } - return BindingSecurity::shouldAllowAccessToFrame(target, DoNotReportSecurityError); + return BindingSecurity::shouldAllowAccessToFrame(isolate, target, DoNotReportSecurityError); } bool V8Window::indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::Handle<v8::Object> window = host->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldTypeInMainThread(isolate))); + v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(host, isolate); if (window.IsEmpty()) return false; - DOMWindow* targetWindow = V8Window::toNative(window); + LocalDOMWindow* targetWindow = V8Window::toNative(window); ASSERT(targetWindow); - Frame* target = targetWindow->frame(); + LocalFrame* target = targetWindow->frame(); if (!target) return false; @@ -516,7 +502,7 @@ bool V8Window::indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t i if (target->loader().stateMachine()->isDisplayingInitialEmptyDocument()) target->loader().didAccessInitialDocument(); - Frame* childFrame = target->tree().scopedChild(index); + Frame* childFrame = target->tree().scopedChild(index); // Notice that we can't call HasRealNamedProperty for ACCESS_HAS // because that would generate infinite recursion. @@ -528,36 +514,22 @@ bool V8Window::indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t i && !window->HasRealIndexedProperty(index)) return true; - return BindingSecurity::shouldAllowAccessToFrame(target, DoNotReportSecurityError); + return BindingSecurity::shouldAllowAccessToFrame(isolate, target, DoNotReportSecurityError); } -v8::Handle<v8::Value> toV8(DOMWindow* window, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +v8::Handle<v8::Value> toV8(LocalDOMWindow* window, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { - // Notice that we explicitly ignore creationContext because the DOMWindow is its own creationContext. + // Notice that we explicitly ignore creationContext because the LocalDOMWindow is its own creationContext. if (!window) return v8::Null(isolate); // Initializes environment of a frame, and return the global object // of the frame. - Frame* frame = window->frame(); + LocalFrame* frame = window->frame(); if (!frame) return v8Undefined(); - // Special case: Because of executeScriptInIsolatedWorld() one DOMWindow can have - // multiple contexts and multiple global objects associated with it. When - // code running in one of those contexts accesses the window object, we - // want to return the global object associated with that context, not - // necessarily the first global object associated with that DOMWindow. - v8::Handle<v8::Context> currentContext = isolate->GetCurrentContext(); - v8::Handle<v8::Object> currentGlobal = currentContext->Global(); - v8::Handle<v8::Object> windowWrapper = currentGlobal->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldTypeInMainThread(isolate))); - if (!windowWrapper.IsEmpty()) { - if (V8Window::toNative(windowWrapper) == window) - return currentGlobal; - } - - // Otherwise, return the global object associated with this frame. - v8::Handle<v8::Context> context = frame->script().currentWorldContext(); + v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::current(isolate)); if (context.IsEmpty()) return v8Undefined(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCryptoCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCryptoCustom.cpp deleted file mode 100644 index acf7a114d5a..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCryptoCustom.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8WorkerCrypto.h" - -#include "V8Crypto.h" - -namespace WebCore { - -void V8WorkerCrypto::getRandomValuesMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - V8Crypto::getRandomValuesMethodCustom(info); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCustom.cpp index 19440578be3..01a4a822546 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCustom.cpp @@ -29,13 +29,12 @@ */ #include "config.h" -#include "V8Worker.h" +#include "bindings/core/v8/V8Worker.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "core/workers/Worker.h" #include "core/workers/WorkerGlobalScope.h" #include "wtf/ArrayBuffer.h" @@ -50,18 +49,13 @@ void V8Worker::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value> ArrayBufferArray arrayBuffers; if (info.Length() > 1) { const int transferablesArgIndex = 1; - bool notASequence = false; - if (!extractTransferables(info[transferablesArgIndex], ports, arrayBuffers, notASequence, info.GetIsolate())) { - if (notASequence) { - exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(transferablesArgIndex + 1)); - exceptionState.throwIfNeeded(); - } + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, ports, arrayBuffers, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); return; } } - bool didThrow = false; - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, didThrow, info.GetIsolate()); - if (didThrow) + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; worker->postMessage(message.release(), &ports, exceptionState); exceptionState.throwIfNeeded(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerGlobalScopeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerGlobalScopeCustom.cpp index 1863af5992c..ca43934106b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerGlobalScopeCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerGlobalScopeCustom.cpp @@ -29,27 +29,27 @@ */ #include "config.h" -#include "V8WorkerGlobalScope.h" +#include "bindings/core/v8/V8WorkerGlobalScope.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ScheduledAction.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/V8WorkerGlobalScopeEventListener.h" #include "bindings/v8/WorkerScriptController.h" #include "core/inspector/ScriptCallStack.h" -#include "core/frame/ContentSecurityPolicy.h" #include "core/frame/DOMTimer.h" #include "core/frame/DOMWindowTimers.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/workers/WorkerGlobalScope.h" #include "modules/websockets/WebSocket.h" #include "wtf/OwnPtr.h" namespace WebCore { -void SetTimeoutOrInterval(const v8::FunctionCallbackInfo<v8::Value>& info, bool singleShot) +static void setTimeoutOrInterval(const v8::FunctionCallbackInfo<v8::Value>& info, bool singleShot) { WorkerGlobalScope* workerGlobalScope = V8WorkerGlobalScope::toNative(info.Holder()); + ASSERT(workerGlobalScope); int argumentCount = info.Length(); if (argumentCount < 1) @@ -61,8 +61,8 @@ void SetTimeoutOrInterval(const v8::FunctionCallbackInfo<v8::Value>& info, bool if (!script) return; + ScriptState* scriptState = ScriptState::current(info.GetIsolate()); OwnPtr<ScheduledAction> action; - v8::Handle<v8::Context> v8Context = script->context(); if (function->IsString()) { if (ContentSecurityPolicy* policy = workerGlobalScope->contentSecurityPolicy()) { if (!policy->allowEval()) { @@ -70,7 +70,7 @@ void SetTimeoutOrInterval(const v8::FunctionCallbackInfo<v8::Value>& info, bool return; } } - action = adoptPtr(new ScheduledAction(v8Context, toCoreString(function.As<v8::String>()), workerGlobalScope->url(), info.GetIsolate())); + action = adoptPtr(new ScheduledAction(scriptState, toCoreString(function.As<v8::String>()), workerGlobalScope->url(), info.GetIsolate())); } else if (function->IsFunction()) { size_t paramCount = argumentCount >= 2 ? argumentCount - 2 : 0; OwnPtr<v8::Local<v8::Value>[]> params; @@ -80,28 +80,28 @@ void SetTimeoutOrInterval(const v8::FunctionCallbackInfo<v8::Value>& info, bool params[i] = info[i+2]; } // ScheduledAction takes ownership of actual params and releases them in its destructor. - action = adoptPtr(new ScheduledAction(v8Context, v8::Handle<v8::Function>::Cast(function), paramCount, params.get(), info.GetIsolate())); + action = adoptPtr(new ScheduledAction(scriptState, v8::Handle<v8::Function>::Cast(function), paramCount, params.get(), info.GetIsolate())); } else return; int32_t timeout = argumentCount >= 2 ? info[1]->Int32Value() : 0; int timerId; if (singleShot) - timerId = DOMWindowTimers::setTimeout(workerGlobalScope, action.release(), timeout); + timerId = DOMWindowTimers::setTimeout(*workerGlobalScope, action.release(), timeout); else - timerId = DOMWindowTimers::setInterval(workerGlobalScope, action.release(), timeout); + timerId = DOMWindowTimers::setInterval(*workerGlobalScope, action.release(), timeout); v8SetReturnValue(info, timerId); } void V8WorkerGlobalScope::setTimeoutMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - return SetTimeoutOrInterval(info, true); + return setTimeoutOrInterval(info, true); } void V8WorkerGlobalScope::setIntervalMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - return SetTimeoutOrInterval(info, false); + return setTimeoutOrInterval(info, false); } v8::Handle<v8::Value> toV8(WorkerGlobalScope* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp index 855f64e16bf..8659b65bcff 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp @@ -29,17 +29,16 @@ */ #include "config.h" -#include "V8XMLHttpRequest.h" +#include "bindings/core/v8/V8XMLHttpRequest.h" -#include "V8Blob.h" -#include "V8Document.h" -#include "V8FormData.h" -#include "V8HTMLDocument.h" -#include "V8Stream.h" +#include "bindings/core/v8/V8Blob.h" +#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8FormData.h" +#include "bindings/core/v8/V8HTMLDocument.h" +#include "bindings/core/v8/V8Stream.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "core/dom/Document.h" @@ -54,15 +53,16 @@ namespace WebCore { void V8XMLHttpRequest::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - ExecutionContext* context = getExecutionContext(); + ExecutionContext* context = currentExecutionContext(info.GetIsolate()); RefPtr<SecurityOrigin> securityOrigin; if (context->isDocument()) { - if (DOMWrapperWorld* world = isolatedWorldForEnteredContext(info.GetIsolate())) - securityOrigin = world->isolatedWorldSecurityOrigin(); + DOMWrapperWorld& world = DOMWrapperWorld::current(info.GetIsolate()); + if (world.isIsolatedWorld()) + securityOrigin = world.isolatedWorldSecurityOrigin(); } - RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context, securityOrigin); + RefPtrWillBeRawPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context, securityOrigin); v8::Handle<v8::Object> wrapper = info.Holder(); V8DOMWrapper::associateObjectWithWrapper<V8XMLHttpRequest>(xmlHttpRequest.release(), &wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); @@ -73,10 +73,10 @@ void V8XMLHttpRequest::responseTextAttributeGetterCustom(const v8::PropertyCallb { XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(info.Holder()); ExceptionState exceptionState(ExceptionState::GetterContext, "responseText", "XMLHttpRequest", info.Holder(), info.GetIsolate()); - ScriptValue text = xmlHttpRequest->responseText(exceptionState); + ScriptString text = xmlHttpRequest->responseText(exceptionState); if (exceptionState.throwIfNeeded()) return; - if (text.hasNoValue()) { + if (text.isEmpty()) { v8SetReturnValueString(info, emptyString(), info.GetIsolate()); return; } @@ -98,21 +98,18 @@ void V8XMLHttpRequest::responseAttributeGetterCustom(const v8::PropertyCallbackI v8::Isolate* isolate = info.GetIsolate(); ScriptString jsonSource = xmlHttpRequest->responseJSONSource(); - if (jsonSource.hasNoValue() || !jsonSource.v8Value()->IsString()) { + if (jsonSource.isEmpty()) { v8SetReturnValue(info, v8::Null(isolate)); return; } // Catch syntax error. v8::TryCatch exceptionCatcher; - - v8::Handle<v8::Value> json = v8::JSON::Parse(jsonSource.v8Value().As<v8::String>()); - + v8::Handle<v8::Value> json = v8::JSON::Parse(jsonSource.v8Value()); if (exceptionCatcher.HasCaught() || json.IsEmpty()) v8SetReturnValue(info, v8::Null(isolate)); else v8SetReturnValue(info, json); - return; } @@ -170,20 +167,20 @@ void V8XMLHttpRequest::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(info.Holder()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, method, info[0]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, urlstring, info[1]); + TOSTRING_VOID(V8StringResource<>, method, info[0]); + TOSTRING_VOID(V8StringResource<>, urlstring, info[1]); - ExecutionContext* context = getExecutionContext(); + ExecutionContext* context = currentExecutionContext(info.GetIsolate()); KURL url = context->completeURL(urlstring); if (info.Length() >= 3) { bool async = info[2]->BooleanValue(); if (info.Length() >= 4 && !info[3]->IsUndefined()) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, user, info[3]); + TOSTRING_VOID(V8StringResource<WithNullCheck>, user, info[3]); if (info.Length() >= 5 && !info[4]->IsUndefined()) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, password, info[4]); + TOSTRING_VOID(V8StringResource<WithNullCheck>, password, info[4]); xmlHttpRequest->open(method, url, async, user, password, exceptionState); } else { xmlHttpRequest->open(method, url, async, user, exceptionState); @@ -198,10 +195,10 @@ void V8XMLHttpRequest::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value exceptionState.throwIfNeeded(); } -static bool isDocumentType(v8::Handle<v8::Value> value, v8::Isolate* isolate, WrapperWorldType currentWorldType) +static bool isDocumentType(v8::Handle<v8::Value> value, v8::Isolate* isolate) { // FIXME: add other document types. - return V8Document::hasInstance(value, isolate, currentWorldType) || V8HTMLDocument::hasInstance(value, isolate, currentWorldType); + return V8Document::hasInstance(value, isolate) || V8HTMLDocument::hasInstance(value, isolate); } void V8XMLHttpRequest::sendMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -215,36 +212,35 @@ void V8XMLHttpRequest::sendMethodCustom(const v8::FunctionCallbackInfo<v8::Value xmlHttpRequest->send(exceptionState); else { v8::Handle<v8::Value> arg = info[0]; - WrapperWorldType currentWorldType = worldType(info.GetIsolate()); if (isUndefinedOrNull(arg)) { xmlHttpRequest->send(exceptionState); - } else if (isDocumentType(arg, info.GetIsolate(), currentWorldType)) { + } else if (isDocumentType(arg, info.GetIsolate())) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); Document* document = V8Document::toNative(object); ASSERT(document); xmlHttpRequest->send(document, exceptionState); - } else if (V8Blob::hasInstance(arg, info.GetIsolate(), currentWorldType)) { + } else if (V8Blob::hasInstance(arg, info.GetIsolate())) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); Blob* blob = V8Blob::toNative(object); ASSERT(blob); xmlHttpRequest->send(blob, exceptionState); - } else if (V8FormData::hasInstance(arg, info.GetIsolate(), currentWorldType)) { + } else if (V8FormData::hasInstance(arg, info.GetIsolate())) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); DOMFormData* domFormData = V8FormData::toNative(object); ASSERT(domFormData); xmlHttpRequest->send(domFormData, exceptionState); - } else if (V8ArrayBuffer::hasInstance(arg, info.GetIsolate(), currentWorldType)) { + } else if (V8ArrayBuffer::hasInstance(arg, info.GetIsolate())) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(object); ASSERT(arrayBuffer); xmlHttpRequest->send(arrayBuffer, exceptionState); - } else if (V8ArrayBufferView::hasInstance(arg, info.GetIsolate(), currentWorldType)) { + } else if (V8ArrayBufferView::hasInstance(arg, info.GetIsolate())) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object); ASSERT(arrayBufferView); xmlHttpRequest->send(arrayBufferView, exceptionState); } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, argString, arg); + TOSTRING_VOID(V8StringResource<WithNullCheck>, argString, arg); xmlHttpRequest->send(argString, exceptionState); } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp index 7835310a652..2c7591f1dde 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp @@ -29,11 +29,11 @@ */ #include "config.h" -#include "V8XSLTProcessor.h" +#include "bindings/core/v8/V8XSLTProcessor.h" -#include "V8Document.h" -#include "V8DocumentFragment.h" -#include "V8Node.h" +#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8DocumentFragment.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/V8Binding.h" #include "core/dom/Document.h" #include "core/dom/DocumentFragment.h" @@ -48,12 +48,12 @@ void V8XSLTProcessor::setParameterMethodCustom(const v8::FunctionCallbackInfo<v8 if (isUndefinedOrNull(info[1]) || isUndefinedOrNull(info[2])) return; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, info[0]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, localName, info[1]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, value, info[2]); + TOSTRING_VOID(V8StringResource<>, namespaceURI, info[0]); + TOSTRING_VOID(V8StringResource<>, localName, info[1]); + TOSTRING_VOID(V8StringResource<>, value, info[2]); - XSLTProcessor* imp = V8XSLTProcessor::toNative(info.Holder()); - imp->setParameter(namespaceURI, localName, value); + XSLTProcessor* impl = V8XSLTProcessor::toNative(info.Holder()); + impl->setParameter(namespaceURI, localName, value); } void V8XSLTProcessor::getParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -61,11 +61,11 @@ void V8XSLTProcessor::getParameterMethodCustom(const v8::FunctionCallbackInfo<v8 if (isUndefinedOrNull(info[1])) return; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, info[0]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, localName, info[1]); + TOSTRING_VOID(V8StringResource<>, namespaceURI, info[0]); + TOSTRING_VOID(V8StringResource<>, localName, info[1]); - XSLTProcessor* imp = V8XSLTProcessor::toNative(info.Holder()); - String result = imp->getParameter(namespaceURI, localName); + XSLTProcessor* impl = V8XSLTProcessor::toNative(info.Holder()); + String result = impl->getParameter(namespaceURI, localName); if (result.isNull()) return; @@ -77,11 +77,11 @@ void V8XSLTProcessor::removeParameterMethodCustom(const v8::FunctionCallbackInfo if (isUndefinedOrNull(info[1])) return; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, info[0]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, localName, info[1]); + TOSTRING_VOID(V8StringResource<>, namespaceURI, info[0]); + TOSTRING_VOID(V8StringResource<>, localName, info[1]); - XSLTProcessor* imp = V8XSLTProcessor::toNative(info.Holder()); - imp->removeParameter(namespaceURI, localName); + XSLTProcessor* impl = V8XSLTProcessor::toNative(info.Holder()); + impl->removeParameter(namespaceURI, localName); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/custom.gypi b/chromium/third_party/WebKit/Source/bindings/v8/custom/custom.gypi new file mode 100644 index 00000000000..9d76a6e41ad --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/custom.gypi @@ -0,0 +1,92 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'bindings_v8_custom_files': [ + 'V8ArrayBufferCustom.cpp', + 'V8ArrayBufferCustom.h', + 'V8ArrayBufferViewCustom.cpp', + 'V8ArrayBufferViewCustom.h', + 'V8AudioNodeCustom.cpp', + 'V8BlobCustom.cpp', + 'V8BlobCustomHelpers.cpp', + 'V8BlobCustomHelpers.h', + 'V8CSSRuleCustom.cpp', + 'V8CSSStyleDeclarationCustom.cpp', + 'V8CSSValueCustom.cpp', + 'V8CanvasRenderingContext2DCustom.cpp', + 'V8ClientCustom.cpp', + 'V8CryptoCustom.cpp', + 'V8CustomEventCustom.cpp', + 'V8CustomSQLStatementErrorCallback.cpp', + 'V8CustomXPathNSResolver.cpp', + 'V8CustomXPathNSResolver.h', + 'V8DataViewCustom.cpp', + 'V8DataViewCustom.h', + 'V8DedicatedWorkerGlobalScopeCustom.cpp', + 'V8DeviceMotionEventCustom.cpp', + 'V8DeviceOrientationEventCustom.cpp', + 'V8DocumentCustom.cpp', + 'V8ElementCustom.cpp', + 'V8EntryCustom.cpp', + 'V8EntrySyncCustom.cpp', + 'V8ErrorEventCustom.cpp', + 'V8EventCustom.cpp', + 'V8EventTargetCustom.cpp', + 'V8FileCustom.cpp', + 'V8FileReaderCustom.cpp', + 'V8Float32ArrayCustom.h', + 'V8Float64ArrayCustom.h', + 'V8GeolocationCustom.cpp', + 'V8HTMLAllCollectionCustom.cpp', + 'V8HTMLCanvasElementCustom.cpp', + 'V8HTMLCollectionCustom.cpp', + 'V8HTMLDocumentCustom.cpp', + 'V8HTMLElementCustom.cpp', + 'V8HTMLOptionsCollectionCustom.cpp', + 'V8HTMLPlugInElementCustom.cpp', + 'V8HistoryCustom.cpp', + 'V8ImageDataCustom.cpp', + 'V8InjectedScriptHostCustom.cpp', + 'V8InjectedScriptManager.cpp', + 'V8InspectorFrontendHostCustom.cpp', + 'V8Int16ArrayCustom.h', + 'V8Int32ArrayCustom.h', + 'V8Int8ArrayCustom.h', + 'V8JavaScriptCallFrameCustom.cpp', + 'V8LocationCustom.cpp', + 'V8MessageChannelCustom.cpp', + 'V8MessageEventCustom.cpp', + 'V8MessagePortCustom.cpp', + 'V8MutationObserverCustom.cpp', + 'V8NodeCustom.cpp', + 'V8PerformanceEntryCustom.cpp', + 'V8PopStateEventCustom.cpp', + 'V8SQLResultSetRowListCustom.cpp', + 'V8SQLTransactionCustom.cpp', + 'V8SQLTransactionSyncCustom.cpp', + 'V8SVGElementCustom.cpp', + 'V8SVGPathSegCustom.cpp', + 'V8ServiceWorkerCustom.cpp', + 'V8StyleSheetCustom.cpp', + 'V8SubtleCryptoCustom.cpp', + 'V8TextCustom.cpp', + 'V8TextTrackCueCustom.cpp', + 'V8TrackEventCustom.cpp', + 'V8TypedArrayCustom.h', + 'V8Uint16ArrayCustom.h', + 'V8Uint32ArrayCustom.h', + 'V8Uint8ArrayCustom.h', + 'V8Uint8ClampedArrayCustom.h', + 'V8WebGLRenderingContextCustom.cpp', + 'V8WebKitPointCustom.cpp', + 'V8WindowCustom.cpp', + 'V8WorkerCustom.cpp', + 'V8WorkerGlobalScopeCustom.cpp', + 'V8XMLHttpRequestCustom.cpp', + 'V8XSLTProcessorCustom.cpp', + ], + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/v8/npruntime.cpp b/chromium/third_party/WebKit/Source/bindings/v8/npruntime.cpp index d3e1755f100..182845e8810 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/npruntime.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/npruntime.cpp @@ -352,7 +352,7 @@ void _NPN_InitializeVariantWithStringCopy(NPVariant* variant, const NPString* va // The rootObjectMap is a hash table of root objects to a set of // objects that should be deactivated in sync with the root. A // root is defined as a top-level owner object. This is used on -// Frame teardown to deactivate all objects associated +// LocalFrame teardown to deactivate all objects associated // with a particular plugin. typedef WTF::HashSet<NPObject*> NPObjectSet; @@ -432,7 +432,7 @@ void _NPN_UnregisterObject(NPObject* npObject) set->remove(sub_object); liveObjectMap().remove(sub_object); - // Script objects hold a refernce to their DOMWindow*, which is going away if + // Script objects hold a refernce to their LocalDOMWindow*, which is going away if // we're unregistering the associated owner NPObject. Clear it out. if (V8NPObject* v8npObject = npObjectToV8NPObject(sub_object)) v8npObject->rootObject = 0; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/v8.gypi b/chromium/third_party/WebKit/Source/bindings/v8/v8.gypi new file mode 100644 index 00000000000..a220a63087e --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/v8.gypi @@ -0,0 +1,165 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'includes': [ + 'custom/custom.gypi', + ], + 'variables': { + 'bindings_v8_dir': '.', + 'bindings_v8_files': [ + '<@(bindings_v8_custom_files)', + 'ActiveDOMCallback.cpp', + 'ActiveDOMCallback.h', + 'ArrayValue.cpp', + 'ArrayValue.h', + 'BindingSecurity.cpp', + 'BindingSecurity.h', + 'CallbackPromiseAdapter.h', + 'CustomElementBinding.cpp', + 'CustomElementBinding.h', + 'CustomElementConstructorBuilder.cpp', + 'CustomElementConstructorBuilder.h', + 'CustomElementWrapper.cpp', + 'CustomElementWrapper.h', + 'DOMDataStore.cpp', + 'DOMDataStore.h', + 'DOMWrapperMap.h', + 'DOMWrapperWorld.cpp', + 'DOMWrapperWorld.h', + 'Dictionary.cpp', + 'Dictionary.h', + 'ExceptionMessages.cpp', + 'ExceptionMessages.h', + 'ExceptionState.cpp', + 'ExceptionState.h', + 'ExceptionStatePlaceholder.cpp', + 'ExceptionStatePlaceholder.h', + 'IDBBindingUtilities.cpp', + 'IDBBindingUtilities.h', + 'NPV8Object.cpp', + 'NPV8Object.h', + 'Nullable.h', + 'PageScriptDebugServer.cpp', + 'PageScriptDebugServer.h', + 'RetainedDOMInfo.cpp', + 'RetainedDOMInfo.h', + 'RetainedObjectInfo.h', + 'ScheduledAction.cpp', + 'ScheduledAction.h', + 'ScopedPersistent.h', + 'ScriptCallStackFactory.cpp', + 'ScriptCallStackFactory.h', + 'ScriptController.cpp', + 'ScriptController.h', + 'ScriptDebugServer.cpp', + 'ScriptDebugServer.h', + 'ScriptEventListener.cpp', + 'ScriptEventListener.h', + 'ScriptFunction.cpp', + 'ScriptFunction.h', + 'ScriptFunctionCall.cpp', + 'ScriptFunctionCall.h', + 'ScriptGCEvent.cpp', + 'ScriptGCEvent.h', + 'ScriptHeapSnapshot.cpp', + 'ScriptHeapSnapshot.h', + 'ScriptPreprocessor.cpp', + 'ScriptPreprocessor.h', + 'ScriptProfiler.cpp', + 'ScriptProfiler.h', + 'ScriptPromise.cpp', + 'ScriptPromise.h', + 'ScriptPromiseResolver.cpp', + 'ScriptPromiseResolver.h', + 'ScriptPromiseResolverWithContext.cpp', + 'ScriptPromiseResolverWithContext.h', + 'ScriptRegexp.cpp', + 'ScriptRegexp.h', + 'ScriptSourceCode.h', + 'ScriptState.cpp', + 'ScriptState.h', + 'ScriptString.cpp', + 'ScriptString.h', + 'ScriptValue.cpp', + 'ScriptValue.h', + 'ScriptWrappable.h', + 'SerializedScriptValue.cpp', + 'SerializedScriptValue.h', + 'SharedPersistent.h', + 'V8AbstractEventListener.cpp', + 'V8AbstractEventListener.h', + 'V8Binding.cpp', + 'V8Binding.h', + 'V8BindingMacros.h', + 'V8Callback.cpp', + 'V8Callback.h', + 'V8CustomElementLifecycleCallbacks.cpp', + 'V8CustomElementLifecycleCallbacks.h', + 'V8DOMActivityLogger.cpp', + 'V8DOMActivityLogger.h', + 'V8DOMConfiguration.cpp', + 'V8DOMConfiguration.h', + 'V8DOMWrapper.cpp', + 'V8DOMWrapper.h', + 'V8ErrorHandler.cpp', + 'V8ErrorHandler.h', + 'V8EventListener.cpp', + 'V8EventListener.h', + 'V8EventListenerList.cpp', + 'V8EventListenerList.h', + 'V8GCController.cpp', + 'V8GCController.h', + 'V8GCForContextDispose.cpp', + 'V8GCForContextDispose.h', + 'V8HiddenValue.cpp', + 'V8HiddenValue.h', + 'V8Initializer.cpp', + 'V8Initializer.h', + 'V8LazyEventListener.cpp', + 'V8LazyEventListener.h', + 'V8MutationCallback.cpp', + 'V8MutationCallback.h', + 'V8NPObject.cpp', + 'V8NPObject.h', + 'V8NPUtils.cpp', + 'V8NPUtils.h', + 'V8NodeFilterCondition.cpp', + 'V8NodeFilterCondition.h', + 'V8ObjectConstructor.cpp', + 'V8ObjectConstructor.h', + 'V8PerContextData.cpp', + 'V8PerContextData.h', + 'V8PerIsolateData.cpp', + 'V8PerIsolateData.h', + 'V8RecursionScope.cpp', + 'V8RecursionScope.h', + 'V8ScriptRunner.cpp', + 'V8ScriptRunner.h', + 'V8StringResource.cpp', + 'V8StringResource.h', + 'V8ThrowException.cpp', + 'V8ThrowException.h', + 'V8ValueCache.cpp', + 'V8ValueCache.h', + 'V8WindowShell.cpp', + 'V8WindowShell.h', + 'V8WorkerGlobalScopeEventListener.cpp', + 'V8WorkerGlobalScopeEventListener.h', + 'WorkerScriptController.cpp', + 'WorkerScriptController.h', + 'WorkerScriptDebugServer.cpp', + 'WorkerScriptDebugServer.h', + 'WrapperTypeInfo.h', + 'npruntime.cpp', + 'npruntime_impl.h', + 'npruntime_priv.h', + ], + 'bindings_v8_unittest_files': [ + 'IDBBindingUtilitiesTest.cpp', + 'ScriptPromiseResolverTest.cpp', + 'ScriptPromiseTest.cpp', + ], + }, +} |