Merge from Chromium at DEPS revision r212014
This commit was generated by merge_to_master.py.
Change-Id: Ib07d03553a1e81485ac4ffc92b91e977c4875409
diff --git a/Source/bindings/v8/V8CustomElementCallback.h b/Source/bindings/v8/CustomElementBinding.cpp
similarity index 65%
copy from Source/bindings/v8/V8CustomElementCallback.h
copy to Source/bindings/v8/CustomElementBinding.cpp
index 24becc1..4f7e74e 100644
--- a/Source/bindings/v8/V8CustomElementCallback.h
+++ b/Source/bindings/v8/CustomElementBinding.cpp
@@ -28,35 +28,23 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef V8CustomElementCallback_h
-#define V8CustomElementCallback_h
-
-#include "bindings/v8/ActiveDOMCallback.h"
-#include "bindings/v8/DOMWrapperWorld.h"
-#include "bindings/v8/ScopedPersistent.h"
-#include "core/dom/CustomElementCallback.h"
-#include <v8.h>
+#include "config.h"
+#include "bindings/v8/CustomElementBinding.h"
namespace WebCore {
-class Element;
-class ScriptExecutionContext;
-
-class V8CustomElementCallback : public CustomElementCallback, ActiveDOMCallback {
-public:
- static PassRefPtr<V8CustomElementCallback> create(ScriptExecutionContext*, v8::Handle<v8::Object> owner, v8::Handle<v8::Function> ready);
-
- virtual ~V8CustomElementCallback() { }
-
-private:
- V8CustomElementCallback(ScriptExecutionContext*, v8::Handle<v8::Function> ready);
-
- virtual void ready(Element*) OVERRIDE;
-
- RefPtr<DOMWrapperWorld> m_world;
- ScopedPersistent<v8::Function> m_ready;
-};
-
+PassOwnPtr<CustomElementBinding> CustomElementBinding::create(v8::Isolate* isolate, v8::Handle<v8::Object> prototype, WrapperTypeInfo* wrapperType)
+{
+ return adoptPtr(new CustomElementBinding(isolate, prototype, wrapperType));
}
-#endif // CustomElementCallback_h
+CustomElementBinding::CustomElementBinding(v8::Isolate* isolate, v8::Handle<v8::Object> prototype, WrapperTypeInfo* wrapperType)
+ : m_isolate(isolate)
+ , m_prototype(isolate, prototype)
+ , m_wrapperType(wrapperType)
+{
+ ASSERT(m_prototype.value());
+ ASSERT(m_wrapperType);
+}
+
+} // namespace WebCore
diff --git a/Source/bindings/v8/V8CustomElementCallback.h b/Source/bindings/v8/CustomElementBinding.h
similarity index 67%
rename from Source/bindings/v8/V8CustomElementCallback.h
rename to Source/bindings/v8/CustomElementBinding.h
index 24becc1..ff29d1d 100644
--- a/Source/bindings/v8/V8CustomElementCallback.h
+++ b/Source/bindings/v8/CustomElementBinding.h
@@ -28,35 +28,34 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef V8CustomElementCallback_h
-#define V8CustomElementCallback_h
+#ifndef CustomElementBinding_h
+#define CustomElementBinding_h
-#include "bindings/v8/ActiveDOMCallback.h"
-#include "bindings/v8/DOMWrapperWorld.h"
-#include "bindings/v8/ScopedPersistent.h"
-#include "core/dom/CustomElementCallback.h"
+#include "bindings/v8/UnsafePersistent.h"
+#include "wtf/PassOwnPtr.h"
#include <v8.h>
namespace WebCore {
-class Element;
-class ScriptExecutionContext;
+struct WrapperTypeInfo;
-class V8CustomElementCallback : public CustomElementCallback, ActiveDOMCallback {
+class CustomElementBinding {
public:
- static PassRefPtr<V8CustomElementCallback> create(ScriptExecutionContext*, v8::Handle<v8::Object> owner, v8::Handle<v8::Function> ready);
+ static PassOwnPtr<CustomElementBinding> create(v8::Isolate*, v8::Handle<v8::Object> prototype, WrapperTypeInfo*);
- virtual ~V8CustomElementCallback() { }
+ ~CustomElementBinding() { m_prototype.dispose(); }
+
+ v8::Handle<v8::Object> prototype() { return m_prototype.newLocal(m_isolate); }
+ WrapperTypeInfo* wrapperType() { return m_wrapperType; }
private:
- V8CustomElementCallback(ScriptExecutionContext*, v8::Handle<v8::Function> ready);
+ CustomElementBinding(v8::Isolate*, v8::Handle<v8::Object> prototype, WrapperTypeInfo*);
- virtual void ready(Element*) OVERRIDE;
-
- RefPtr<DOMWrapperWorld> m_world;
- ScopedPersistent<v8::Function> m_ready;
+ v8::Isolate* m_isolate;
+ UnsafePersistent<v8::Object> m_prototype;
+ WrapperTypeInfo* m_wrapperType;
};
}
-#endif // CustomElementCallback_h
+#endif // CustomElementBinding_h
diff --git a/Source/bindings/v8/CustomElementConstructorBuilder.cpp b/Source/bindings/v8/CustomElementConstructorBuilder.cpp
index 05351b0..6e4dd40 100644
--- a/Source/bindings/v8/CustomElementConstructorBuilder.cpp
+++ b/Source/bindings/v8/CustomElementConstructorBuilder.cpp
@@ -36,15 +36,17 @@
#include "V8Document.h"
#include "V8HTMLElementWrapperFactory.h"
#include "V8SVGElementWrapperFactory.h"
-#include "bindings/v8/CustomElementHelpers.h"
+#include "bindings/v8/CustomElementBinding.h"
+#include "bindings/v8/DOMWrapperWorld.h"
#include "bindings/v8/Dictionary.h"
#include "bindings/v8/UnsafePersistent.h"
#include "bindings/v8/V8Binding.h"
-#include "bindings/v8/V8CustomElementCallback.h"
+#include "bindings/v8/V8CustomElementLifecycleCallbacks.h"
#include "bindings/v8/V8HiddenPropertyName.h"
#include "bindings/v8/V8PerContextData.h"
#include "core/dom/CustomElementCallbackDispatcher.h"
#include "core/dom/CustomElementDefinition.h"
+#include "core/dom/CustomElementDescriptor.h"
#include "core/dom/Document.h"
#include "wtf/Assertions.h"
#include "wtf/RefPtr.h"
@@ -56,13 +58,15 @@
CustomElementConstructorBuilder::CustomElementConstructorBuilder(ScriptState* state, const Dictionary* options)
: m_context(state->context())
, m_options(options)
+ , m_wrapperType(0)
{
ASSERT(m_context == v8::Isolate::GetCurrent()->GetCurrentContext());
}
bool CustomElementConstructorBuilder::isFeatureAllowed() const
{
- return CustomElementHelpers::isFeatureAllowed(m_context);
+ // Check that we are in the main world
+ return !DOMWrapperWorld::isolatedWorld(m_context);
}
bool CustomElementConstructorBuilder::validateOptions()
@@ -82,7 +86,7 @@
v8::Handle<v8::Value> prototypeValue = prototypeScriptValue.v8Value();
if (prototypeValue.IsEmpty() || !prototypeValue->IsObject())
return false;
- m_prototype = v8::Handle<v8::Object>::Cast(prototypeValue);
+ m_prototype = prototypeValue.As<v8::Object>();
V8PerContextData* perContextData;
if (!(perContextData = V8PerContextData::from(m_context))) {
@@ -109,23 +113,23 @@
return false;
}
-bool CustomElementConstructorBuilder::findTagName(const AtomicString& customElementType, QualifiedName& tagName) const
+bool CustomElementConstructorBuilder::findTagName(const AtomicString& customElementType, QualifiedName& tagName)
{
ASSERT(!m_prototype.IsEmpty());
- WrapperTypeInfo* wrapperTypeInfo = CustomElementHelpers::findWrapperType(m_prototype);
- if (!wrapperTypeInfo) {
+ m_wrapperType = findWrapperType(m_prototype);
+ if (!m_wrapperType) {
// Invalid prototype.
return false;
}
- if (const QualifiedName* htmlName = findHTMLTagNameOfV8Type(wrapperTypeInfo)) {
+ if (const QualifiedName* htmlName = findHTMLTagNameOfV8Type(m_wrapperType)) {
ASSERT(htmlName->namespaceURI() == m_namespaceURI);
tagName = *htmlName;
return true;
}
- if (const QualifiedName* svgName = findSVGTagNameOfV8Type(wrapperTypeInfo)) {
+ if (const QualifiedName* svgName = findSVGTagNameOfV8Type(m_wrapperType)) {
ASSERT(svgName->namespaceURI() == m_namespaceURI);
tagName = *svgName;
return true;
@@ -140,7 +144,7 @@
return false;
}
-PassRefPtr<CustomElementCallback> CustomElementConstructorBuilder::createCallback(Document* document)
+PassRefPtr<CustomElementLifecycleCallbacks> CustomElementConstructorBuilder::createCallbacks(Document* document)
{
ASSERT(!m_prototype.IsEmpty());
@@ -150,13 +154,20 @@
exceptionCatcher.SetVerbose(true);
v8::Isolate* isolate = v8::Isolate::GetCurrent();
- v8::Handle<v8::Value> readyValue = m_prototype->Get(v8String("readyCallback", isolate));
+ v8::Handle<v8::Function> created = retrieveCallback(isolate, "createdCallback");
+ v8::Handle<v8::Function> enteredDocument = retrieveCallback(isolate, "enteredDocumentCallback");
+ v8::Handle<v8::Function> leftDocument = retrieveCallback(isolate, "leftDocumentCallback");
+ v8::Handle<v8::Function> attributeChanged = retrieveCallback(isolate, "attributeChangedCallback");
- v8::Handle<v8::Function> readyFunction;
- if (!readyValue.IsEmpty() && readyValue->IsFunction())
- readyFunction = v8::Handle<v8::Function>::Cast(readyValue);
+ return V8CustomElementLifecycleCallbacks::create(document, m_prototype, created, enteredDocument, leftDocument, attributeChanged);
+}
- return V8CustomElementCallback::create(document, m_prototype, readyFunction);
+v8::Handle<v8::Function> CustomElementConstructorBuilder::retrieveCallback(v8::Isolate* isolate, const char* name)
+{
+ v8::Handle<v8::Value> value = m_prototype->Get(v8String(name, isolate));
+ if (value.IsEmpty() || !value->IsFunction())
+ return v8::Handle<v8::Function>();
+ return value.As<v8::Function>();
}
bool CustomElementConstructorBuilder::createConstructor(Document* document, CustomElementDefinition* definition)
@@ -176,15 +187,21 @@
if (m_constructor.IsEmpty())
return false;
- v8::Handle<v8::String> v8Name = v8String(definition->name(), isolate);
- v8::Handle<v8::Value> v8Type = v8StringOrNull(definition->isTypeExtension() ? definition->type() : nullAtom, isolate);
+ const CustomElementDescriptor& descriptor = definition->descriptor();
- m_constructor->SetName(v8Type->IsNull() ? v8Name : v8::Handle<v8::String>::Cast(v8Type));
+ v8::Handle<v8::String> v8TagName = v8String(descriptor.localName(), isolate);
+ v8::Handle<v8::Value> v8Type;
+ if (descriptor.isTypeExtension())
+ v8Type = v8String(descriptor.type(), isolate);
+ else
+ v8Type = v8::Null(isolate);
- V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "document", toV8(document, m_context->Global(), isolate));
- V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "namespaceURI", v8String(definition->namespaceURI(), isolate));
- V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "name", v8Name);
- V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "type", v8Type);
+ 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(descriptor.namespaceURI(), isolate));
+ V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "customElementTagName", v8TagName);
+ V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "customElementType", v8Type);
v8::Handle<v8::String> prototypeKey = v8String("prototype", isolate);
ASSERT(m_constructor->HasOwnProperty(prototypeKey));
@@ -197,7 +214,7 @@
// property.
m_constructor->ForceSet(prototypeKey, m_prototype, v8::PropertyAttribute(v8::ReadOnly | v8::DontEnum | v8::DontDelete));
- V8HiddenPropertyName::setNamedHiddenReference(m_prototype, "isCustomElementInterfacePrototypeObject", v8::True());
+ V8HiddenPropertyName::setNamedHiddenReference(m_prototype, "customElementIsInterfacePrototypeObject", v8::True());
m_prototype->ForceSet(v8String("constructor", isolate), m_constructor, v8::DontEnum);
return true;
@@ -205,8 +222,8 @@
bool CustomElementConstructorBuilder::prototypeIsValid() const
{
- if (m_prototype->InternalFieldCount() || !m_prototype->GetHiddenValue(V8HiddenPropertyName::isCustomElementInterfacePrototypeObject()).IsEmpty()) {
- // Already an interface prototype object.
+ if (m_prototype->InternalFieldCount() || !m_prototype->GetHiddenValue(V8HiddenPropertyName::customElementIsInterfacePrototypeObject()).IsEmpty()) {
+ // Alcreated an interface prototype object.
return false;
}
@@ -218,7 +235,7 @@
return true;
}
-bool CustomElementConstructorBuilder::didRegisterDefinition(CustomElementDefinition* definition, const HashSet<Element*>& upgradeCandidates) const
+bool CustomElementConstructorBuilder::didRegisterDefinition(CustomElementDefinition* definition) const
{
ASSERT(!m_constructor.IsEmpty());
@@ -227,19 +244,7 @@
return false;
// Bindings retrieve the prototype when needed from per-context data.
- v8::Persistent<v8::Object> persistentPrototype(m_context->GetIsolate(), m_prototype);
- perContextData->customElementPrototypes()->add(definition->type(), UnsafePersistent<v8::Object>(persistentPrototype));
-
- // Upgrade any wrappers already created for this definition
- for (HashSet<Element*>::const_iterator it = upgradeCandidates.begin(); it != upgradeCandidates.end(); ++it) {
- v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapperForMainWorld(*it);
- if (wrapper.IsEmpty()) {
- // The wrapper will be created with the right prototype when
- // retrieved; we don't need to eagerly create the wrapper.
- continue;
- }
- wrapper->SetPrototype(m_prototype);
- }
+ perContextData->addCustomElementBinding(definition->descriptor().type(), CustomElementBinding::create(m_context->GetIsolate(), m_prototype, m_wrapperType));
return true;
}
@@ -249,12 +254,26 @@
return ScriptValue(m_constructor);
}
+WrapperTypeInfo* CustomElementConstructorBuilder::findWrapperType(v8::Handle<v8::Value> chain)
+{
+ while (!chain.IsEmpty() && chain->IsObject()) {
+ v8::Handle<v8::Object> chainObject = chain.As<v8::Object>();
+ // Only prototype objects of native-backed types have the extra internal field storing WrapperTypeInfo.
+ if (v8PrototypeInternalFieldcount == chainObject->InternalFieldCount()) {
+ WrapperTypeInfo* wrapperType = reinterpret_cast<WrapperTypeInfo*>(chainObject->GetAlignedPointerFromInternalField(v8PrototypeTypeIndex));
+ ASSERT(wrapperType);
+ return wrapperType;
+ }
+ chain = chainObject->GetPrototype();
+ }
+
+ return 0;
+}
+
bool CustomElementConstructorBuilder::hasValidPrototypeChainFor(V8PerContextData* perContextData, WrapperTypeInfo* typeInfo) const
{
- v8::Handle<v8::Object> elementConstructor = v8::Handle<v8::Object>::Cast(perContextData->constructorForType(typeInfo));
- if (elementConstructor.IsEmpty())
- return false;
- v8::Handle<v8::Object> elementPrototype = v8::Handle<v8::Object>::Cast(elementConstructor->Get(v8String("prototype", m_context->GetIsolate())));
+ v8::Handle<v8::Object> elementConstructor = perContextData->constructorForType(typeInfo);
+ v8::Handle<v8::Object> elementPrototype = elementConstructor->Get(v8String("prototype", m_context->GetIsolate())).As<v8::Object>();
if (elementPrototype.IsEmpty())
return false;
@@ -262,7 +281,7 @@
while (!chain.IsEmpty() && chain->IsObject()) {
if (chain == elementPrototype)
return true;
- chain = v8::Handle<v8::Object>::Cast(chain)->GetPrototype();
+ chain = chain.As<v8::Object>()->GetPrototype();
}
return false;
@@ -282,15 +301,15 @@
return;
}
- Document* document = V8Document::toNative(v8::Handle<v8::Object>::Cast(args.Callee()->GetHiddenValue(V8HiddenPropertyName::document())));
- V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, args.Callee()->GetHiddenValue(V8HiddenPropertyName::namespaceURI()));
- V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, args.Callee()->GetHiddenValue(V8HiddenPropertyName::name()));
- v8::Handle<v8::Value> maybeType = args.Callee()->GetHiddenValue(V8HiddenPropertyName::type());
+ Document* document = V8Document::toNative(args.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementDocument()).As<v8::Object>());
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, args.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementNamespaceURI()));
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, tagName, args.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementTagName()));
+ v8::Handle<v8::Value> maybeType = args.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementType());
V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, maybeType);
ExceptionCode ec = 0;
CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
- RefPtr<Element> element = document->createElementNS(namespaceURI, name, maybeType->IsNull() ? nullAtom : type, ec);
+ RefPtr<Element> element = document->createElementNS(namespaceURI, tagName, maybeType->IsNull() ? nullAtom : type, ec);
if (ec) {
setDOMException(ec, isolate);
return;
diff --git a/Source/bindings/v8/CustomElementConstructorBuilder.h b/Source/bindings/v8/CustomElementConstructorBuilder.h
index c378407..83d5e25 100644
--- a/Source/bindings/v8/CustomElementConstructorBuilder.h
+++ b/Source/bindings/v8/CustomElementConstructorBuilder.h
@@ -32,9 +32,8 @@
#define CustomElementConstructorBuilder_h
#include "bindings/v8/ScriptValue.h"
-#include "core/dom/CustomElementCallback.h"
+#include "core/dom/CustomElementLifecycleCallbacks.h"
#include "core/dom/QualifiedName.h"
-#include "wtf/HashSet.h"
#include "wtf/Noncopyable.h"
#include "wtf/PassRefPtr.h"
#include "wtf/text/AtomicString.h"
@@ -66,10 +65,10 @@
bool isFeatureAllowed() const;
bool validateOptions();
- bool findTagName(const AtomicString& customElementType, QualifiedName& tagName) const;
- PassRefPtr<CustomElementCallback> createCallback(Document*);
+ bool findTagName(const AtomicString& customElementType, QualifiedName& tagName);
+ PassRefPtr<CustomElementLifecycleCallbacks> createCallbacks(Document*);
bool createConstructor(Document*, CustomElementDefinition*);
- bool didRegisterDefinition(CustomElementDefinition*, const HashSet<Element*>& upgradeCandidates) const;
+ bool didRegisterDefinition(CustomElementDefinition*) const;
// This method collects a return value for the bindings. It is
// safe to call this method even if the builder failed; it will
@@ -77,12 +76,15 @@
ScriptValue bindingsReturnValue() const;
private:
+ static WrapperTypeInfo* findWrapperType(v8::Handle<v8::Value> chain);
bool hasValidPrototypeChainFor(V8PerContextData*, WrapperTypeInfo*) const;
bool prototypeIsValid() const;
+ v8::Handle<v8::Function> retrieveCallback(v8::Isolate*, const char* name);
v8::Handle<v8::Context> m_context;
const Dictionary* m_options;
v8::Handle<v8::Object> m_prototype;
+ WrapperTypeInfo* m_wrapperType;
AtomicString m_namespaceURI;
v8::Handle<v8::Function> m_constructor;
};
diff --git a/Source/bindings/v8/CustomElementHelpers.cpp b/Source/bindings/v8/CustomElementHelpers.cpp
deleted file mode 100644
index adbb46b..0000000
--- a/Source/bindings/v8/CustomElementHelpers.cpp
+++ /dev/null
@@ -1,144 +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.
- */
-
-#include "config.h"
-
-#include "bindings/v8/CustomElementHelpers.h"
-
-#include "V8HTMLElementWrapperFactory.h"
-#include "V8SVGElementWrapperFactory.h"
-#include "bindings/v8/DOMWrapperWorld.h"
-#include "bindings/v8/V8PerContextData.h"
-#include "core/dom/CustomElementRegistry.h"
-#include "core/html/HTMLElement.h"
-#include "core/html/HTMLUnknownElement.h"
-#include "core/svg/SVGElement.h"
-
-namespace WebCore {
-
-v8::Handle<v8::Object> CustomElementHelpers::createWrapper(PassRefPtr<Element> impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate, const CreateWrapperFunction& createTypeExtensionUpgradeCandidateWrapper)
-{
- ASSERT(impl);
-
- // 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();
-
- // The constructor and registered lifecycle callbacks should be visible only from main world.
- // FIXME: This shouldn't be needed once each custom element has its own FunctionTemplate
- // https://bugs.webkit.org/show_bug.cgi?id=108138
- if (!CustomElementHelpers::isFeatureAllowed(context)) {
- v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, &V8HTMLElement::info, impl.get(), isolate);
- if (!wrapper.IsEmpty())
- V8DOMWrapper::associateObjectWithWrapper(impl, &V8HTMLElement::info, wrapper, isolate, WrapperConfiguration::Dependent);
- return wrapper;
- }
-
- CustomElementRegistry* registry = impl->document()->registry();
- RefPtr<CustomElementDefinition> definition = registry->findFor(impl.get());
- if (!definition)
- return createUpgradeCandidateWrapper(impl, creationContext, isolate, createTypeExtensionUpgradeCandidateWrapper);
-
- V8PerContextData* perContextData = V8PerContextData::from(context);
- if (!perContextData)
- return v8::Handle<v8::Object>();
-
- v8::Handle<v8::Object> prototype = perContextData->customElementPrototypes()->get(definition->type()).newLocal(isolate);
- WrapperTypeInfo* typeInfo = CustomElementHelpers::findWrapperType(prototype);
- if (!typeInfo) {
- // FIXME: When can this happen?
- return v8::Handle<v8::Object>();
- }
-
- v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, typeInfo, impl.get(), isolate);
- if (wrapper.IsEmpty())
- return v8::Handle<v8::Object>();
-
- wrapper->SetPrototype(prototype);
-
- V8DOMWrapper::associateObjectWithWrapper(impl, typeInfo, wrapper, isolate, WrapperConfiguration::Dependent);
- return wrapper;
-}
-
-v8::Handle<v8::Object> CustomElementHelpers::CreateWrapperFunction::invoke(Element* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) const
-{
- if (element->isHTMLElement()) {
- if (m_html)
- return m_html(toHTMLElement(element), creationContext, isolate);
- return createV8HTMLFallbackWrapper(toHTMLUnknownElement(toHTMLElement(element)), creationContext, isolate);
- } else if (element->isSVGElement()) {
- if (m_svg)
- return m_svg(toSVGElement(element), creationContext, isolate);
- return createV8SVGFallbackWrapper(toSVGElement(element), creationContext, isolate);
- }
-
- ASSERT(0);
- return v8::Handle<v8::Object>();
-}
-
-v8::Handle<v8::Object> CustomElementHelpers::createUpgradeCandidateWrapper(PassRefPtr<Element> element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate, const CreateWrapperFunction& createTypeExtensionUpgradeCandidateWrapper)
-{
- if (CustomElementRegistry::isCustomTagName(element->localName())) {
- if (element->isHTMLElement())
- return createV8HTMLDirectWrapper(toHTMLElement(element.get()), creationContext, isolate);
- else if (element->isSVGElement())
- return createV8SVGDirectWrapper(toSVGElement(element.get()), creationContext, isolate);
- else {
- ASSERT(0);
- return v8::Handle<v8::Object>();
- }
- } else {
- // It's a type extension
- return createTypeExtensionUpgradeCandidateWrapper.invoke(element.get(), creationContext, isolate);
- }
-}
-
-bool CustomElementHelpers::isFeatureAllowed(v8::Handle<v8::Context> context)
-{
- if (DOMWrapperWorld* world = DOMWrapperWorld::isolatedWorld(context))
- return world->isMainWorld();
- return true;
-}
-
-WrapperTypeInfo* CustomElementHelpers::findWrapperType(v8::Handle<v8::Value> chain)
-{
- while (!chain.IsEmpty() && chain->IsObject()) {
- v8::Handle<v8::Object> chainObject = v8::Handle<v8::Object>::Cast(chain);
- // Only prototype objects of native-backed types have the extra internal field storing WrapperTypeInfo.
- if (v8PrototypeInternalFieldcount == chainObject->InternalFieldCount())
- return reinterpret_cast<WrapperTypeInfo*>(chainObject->GetAlignedPointerFromInternalField(v8PrototypeTypeIndex));
- chain = chainObject->GetPrototype();
- }
-
- return 0;
-}
-
-} // namespace WebCore
diff --git a/Source/bindings/v8/CustomElementHelpers.h b/Source/bindings/v8/CustomElementHelpers.h
deleted file mode 100644
index 238eae5..0000000
--- a/Source/bindings/v8/CustomElementHelpers.h
+++ /dev/null
@@ -1,89 +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 CustomElementHelpers_h
-#define CustomElementHelpers_h
-
-#include "bindings/v8/DOMDataStore.h"
-#include "core/dom/Element.h"
-#include "wtf/PassRefPtr.h"
-
-namespace WebCore {
-
-class HTMLElement;
-class SVGElement;
-
-class CustomElementHelpers {
-public:
- static bool isFeatureAllowed(v8::Handle<v8::Context>);
-
- typedef v8::Handle<v8::Object> (*CreateSVGWrapperFunction)(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
- typedef v8::Handle<v8::Object> (*CreateHTMLWrapperFunction)(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
-
- // CustomElementHelpers::wrap is a factory for both HTMLElement
- // and SVGElement wrappers. CreateWrapperFunction is a type safe
- // way of passing a wrapping function for specific elements of
- // either type; it's used as a fallback when creating wrappers for
- // type extensions.
- class CreateWrapperFunction {
- public:
- explicit CreateWrapperFunction(CreateSVGWrapperFunction svg)
- : m_svg(svg) { }
- explicit CreateWrapperFunction(CreateHTMLWrapperFunction html)
- : m_html(html) { }
- v8::Handle<v8::Object> invoke(Element*, v8::Handle<v8::Object> creationContext, v8::Isolate*) const;
- private:
- CreateSVGWrapperFunction m_svg;
- CreateHTMLWrapperFunction m_html;
- };
-
- // You can just use toV8(Node*) to get correct wrapper objects,
- // even for custom elements. Then generated
- // ElementWrapperFactories call V8CustomElement::wrap() with
- // proper prototype instances accordingly.
- static v8::Handle<v8::Object> wrap(Element*, v8::Handle<v8::Object> creationContext, v8::Isolate*, const CreateWrapperFunction& createTypeExtensionUpgradeCandidateWrapper);
-
- static WrapperTypeInfo* findWrapperType(v8::Handle<v8::Value> chain);
-
-private:
- static v8::Handle<v8::Object> createWrapper(PassRefPtr<Element>, v8::Handle<v8::Object>, v8::Isolate*, const CreateWrapperFunction& createTypeExtensionUpgradeCandidateWrapper);
- static v8::Handle<v8::Object> createUpgradeCandidateWrapper(PassRefPtr<Element>, v8::Handle<v8::Object> creationContext, v8::Isolate*, const CreateWrapperFunction& createTypeExtensionUpgradeCandidateWrapper);
-};
-
-inline v8::Handle<v8::Object> CustomElementHelpers::wrap(Element* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate, const CreateWrapperFunction& createWrapper)
-{
- ASSERT(impl);
- ASSERT(DOMDataStore::getWrapper(impl, isolate).IsEmpty());
- return CustomElementHelpers::createWrapper(impl, creationContext, isolate, createWrapper);
-}
-
-} // namespace WebCore
-
-#endif // CustomElementHelpers_h
diff --git a/Source/bindings/v8/CustomElementWrapper.cpp b/Source/bindings/v8/CustomElementWrapper.cpp
new file mode 100644
index 0000000..7bbf5f3
--- /dev/null
+++ b/Source/bindings/v8/CustomElementWrapper.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "bindings/v8/CustomElementWrapper.h"
+
+#include "V8HTMLElement.h"
+#include "V8HTMLElementWrapperFactory.h"
+#include "V8SVGElement.h"
+#include "V8SVGElementWrapperFactory.h"
+#include "bindings/v8/DOMDataStore.h"
+#include "bindings/v8/V8PerContextData.h"
+#include "core/dom/CustomElementRegistrationContext.h"
+#include "core/html/HTMLElement.h"
+#include "core/html/HTMLUnknownElement.h"
+#include "core/svg/SVGElement.h"
+
+namespace WebCore {
+
+template<typename ElementType>
+v8::Handle<v8::Object> createDirectWrapper(ElementType*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
+
+template<>
+v8::Handle<v8::Object> createDirectWrapper<HTMLElement>(HTMLElement* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
+{
+ return createV8HTMLDirectWrapper(element, creationContext, isolate);
+}
+
+template<>
+v8::Handle<v8::Object> createDirectWrapper<SVGElement>(SVGElement* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
+{
+ return createV8SVGDirectWrapper(element, creationContext, isolate);
+}
+
+template<typename ElementType>
+v8::Handle<v8::Object> createFallbackWrapper(ElementType*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
+
+template<>
+v8::Handle<v8::Object> createFallbackWrapper<HTMLElement>(HTMLElement* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
+{
+ return createV8HTMLFallbackWrapper(toHTMLUnknownElement(element), creationContext, isolate);
+}
+
+template<>
+v8::Handle<v8::Object> createFallbackWrapper<SVGElement>(SVGElement* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
+{
+ return createV8SVGFallbackWrapper(element, creationContext, isolate);
+}
+
+template<typename ElementType>
+v8::Handle<v8::Object> createUpgradeCandidateWrapper(ElementType* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate, v8::Handle<v8::Object> (*createSpecificWrapper)(ElementType* element, v8::Handle<v8::Object> creationContext, v8::Isolate*))
+{
+ if (CustomElementRegistrationContext::isCustomTagName(element->localName()))
+ return createDirectWrapper(element, creationContext, isolate);
+ if (createSpecificWrapper)
+ return createSpecificWrapper(element, creationContext, isolate);
+ return createFallbackWrapper(element, creationContext, isolate);
+}
+
+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*))
+{
+ 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();
+
+ if (!element->isUpgradedCustomElement())
+ return createUpgradeCandidateWrapper(element.get(), creationContext, isolate, createSpecificWrapper);
+
+ V8PerContextData* perContextData = V8PerContextData::from(context);
+ if (!perContextData)
+ return v8::Handle<v8::Object>();
+
+ CustomElementDescriptor descriptor = element->document()->registrationContext()->describe(element.get());
+ CustomElementBinding* binding = perContextData->customElementBinding(descriptor.type());
+
+ v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, binding->wrapperType(), element.get(), isolate);
+ if (wrapper.IsEmpty())
+ return v8::Handle<v8::Object>();
+
+ wrapper->SetPrototype(binding->prototype());
+
+ V8DOMWrapper::associateObjectWithWrapper<WrapperType>(element, binding->wrapperType(), wrapper, isolate, WrapperConfiguration::Dependent);
+ return wrapper;
+}
+
+template
+class CustomElementWrapper<HTMLElement, V8HTMLElement>;
+
+template
+class CustomElementWrapper<SVGElement, V8SVGElement>;
+
+} // namespace WebCore
diff --git a/Source/bindings/v8/V8CustomElementCallback.h b/Source/bindings/v8/CustomElementWrapper.h
similarity index 64%
copy from Source/bindings/v8/V8CustomElementCallback.h
copy to Source/bindings/v8/CustomElementWrapper.h
index 24becc1..c3cbbe8 100644
--- a/Source/bindings/v8/V8CustomElementCallback.h
+++ b/Source/bindings/v8/CustomElementWrapper.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
+ * 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
@@ -28,35 +28,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef V8CustomElementCallback_h
-#define V8CustomElementCallback_h
+#ifndef CustomElementWrapper_h
+#define CustomElementWrapper_h
-#include "bindings/v8/ActiveDOMCallback.h"
-#include "bindings/v8/DOMWrapperWorld.h"
-#include "bindings/v8/ScopedPersistent.h"
-#include "core/dom/CustomElementCallback.h"
+#include "wtf/PassRefPtr.h"
#include <v8.h>
namespace WebCore {
-class Element;
-class ScriptExecutionContext;
+class HTMLElement;
+class SVGElement;
-class V8CustomElementCallback : public CustomElementCallback, ActiveDOMCallback {
-public:
- static PassRefPtr<V8CustomElementCallback> create(ScriptExecutionContext*, v8::Handle<v8::Object> owner, v8::Handle<v8::Function> ready);
-
- virtual ~V8CustomElementCallback() { }
-
+template<typename ElementType, typename WrapperType>
+class CustomElementWrapper {
private:
- V8CustomElementCallback(ScriptExecutionContext*, v8::Handle<v8::Function> ready);
+ CustomElementWrapper();
- virtual void ready(Element*) OVERRIDE;
+ 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*);
- RefPtr<DOMWrapperWorld> m_world;
- ScopedPersistent<v8::Function> m_ready;
+ 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*));
};
-}
+} // namespace WebCore
-#endif // CustomElementCallback_h
+#endif // CustomElementWrapper_h
diff --git a/Source/bindings/v8/DOMDataStore.h b/Source/bindings/v8/DOMDataStore.h
index d5f458d..cd12cdc 100644
--- a/Source/bindings/v8/DOMDataStore.h
+++ b/Source/bindings/v8/DOMDataStore.h
@@ -51,8 +51,8 @@
static DOMDataStore* current(v8::Isolate*);
- template<typename T, typename HolderContainer, typename Wrappable>
- static v8::Handle<v8::Object> getWrapperFast(T* object, const HolderContainer& container, Wrappable* holder)
+ template<typename V8T, typename T, typename CallbackInfo, typename Wrappable>
+ static v8::Handle<v8::Object> getWrapperFast(T* object, const CallbackInfo& callbackInfo, Wrappable* holder)
{
// 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
@@ -60,41 +60,41 @@
// 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(container, holder)) {
+ if ((!DOMWrapperWorld::isolatedWorldsExist() && !canExistInWorker(object)) || holderContainsWrapper(callbackInfo, holder)) {
if (ScriptWrappable::wrapperCanBeStoredInObject(object)) {
v8::Handle<v8::Object> result = ScriptWrappable::getUnsafeWrapperFromObject(object).handle();
// Security: always guard against malicious tampering.
- RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result.IsEmpty() || result->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == static_cast<void*>(object));
+ RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result.IsEmpty() || result->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(object));
return result;
}
- return mainWorldStore()->m_wrapperMap.get(object);
+ return mainWorldStore()->m_wrapperMap.get(V8T::toInternalPointer(object));
}
- return current(container.GetIsolate())->get(object);
+ return current(callbackInfo.GetIsolate())->template get<V8T>(object);
}
- template<typename T>
+ 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).handle();
// Security: always guard against malicious tampering.
- RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result.IsEmpty() || result->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == static_cast<void*>(object));
+ RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result.IsEmpty() || result->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(object));
return result;
}
}
- return current(isolate)->get(object);
+ return current(isolate)->template get<V8T>(object);
}
- template<typename T>
+ template<typename V8T, typename T>
static v8::Handle<v8::Object> getWrapperForMainWorld(T* object)
{
if (ScriptWrappable::wrapperCanBeStoredInObject(object))
return ScriptWrappable::getUnsafeWrapperFromObject(object).handle();
- return mainWorldStore()->get(object);
+ return mainWorldStore()->template get<V8T>(object);
}
- template<typename T>
+ 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)) {
@@ -103,21 +103,21 @@
return;
}
}
- return current(isolate)->set(object, wrapper, isolate, configuration);
+ return current(isolate)->template set<V8T>(object, wrapper, isolate, configuration);
}
- template<typename T>
+ template<typename V8T, typename T>
inline v8::Handle<v8::Object> get(T* object)
{
if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld)
return ScriptWrappable::getUnsafeWrapperFromObject(object).handle();
- return m_wrapperMap.get(object);
+ return m_wrapperMap.get(V8T::toInternalPointer(object));
}
void reportMemoryUsage(MemoryObjectInfo*) const;
private:
- template<typename T>
+ template<typename V8T, typename T>
inline void set(T* object, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
{
ASSERT(!!object);
@@ -126,7 +126,7 @@
ScriptWrappable::setWrapperInObject(object, wrapper, isolate, configuration);
return;
}
- m_wrapperMap.set(object, wrapper, configuration);
+ m_wrapperMap.set(V8T::toInternalPointer(object), wrapper, configuration);
}
static DOMDataStore* mainWorldStore();
@@ -134,18 +134,18 @@
static bool canExistInWorker(void*) { return true; }
static bool canExistInWorker(Node*) { return false; }
- template<typename HolderContainer>
- static bool holderContainsWrapper(const HolderContainer&, void*)
+ template<typename CallbackInfo>
+ static bool holderContainsWrapper(const CallbackInfo&, void*)
{
return false;
}
- template<typename HolderContainer>
- static bool holderContainsWrapper(const HolderContainer& container, ScriptWrappable* wrappable)
+ template<typename CallbackInfo>
+ static bool holderContainsWrapper(const CallbackInfo& callbackInfo, ScriptWrappable* wrappable)
{
// Verify our assumptions about the main world.
- ASSERT(wrappable->unsafePersistent().handle().IsEmpty() || container.Holder() != wrappable->unsafePersistent().handle() || current(v8::Isolate::GetCurrent())->m_type == MainWorld);
- return container.Holder() == wrappable->unsafePersistent().handle();
+ ASSERT(wrappable->unsafePersistent().handle().IsEmpty() || callbackInfo.Holder() != wrappable->unsafePersistent().handle() || current(v8::Isolate::GetCurrent())->m_type == MainWorld);
+ return callbackInfo.Holder() == wrappable->unsafePersistent().handle();
}
WrapperWorldType m_type;
diff --git a/Source/bindings/v8/DebuggerScript.js b/Source/bindings/v8/DebuggerScript.js
index 5760f7d..f1d5840 100644
--- a/Source/bindings/v8/DebuggerScript.js
+++ b/Source/bindings/v8/DebuggerScript.js
@@ -163,7 +163,8 @@
DebuggerScript.setBreakpoint = function(execState, args)
{
- var breakId = Debug.setScriptBreakPointById(args.sourceID, args.lineNumber, args.columnNumber, args.condition);
+ var positionAlignment = args.interstatementLocation ? Debug.BreakPositionAlignment.BreakPosition : Debug.BreakPositionAlignment.Statement;
+ var breakId = Debug.setScriptBreakPointById(args.sourceID, args.lineNumber, args.columnNumber, args.condition, undefined, positionAlignment);
var locations = Debug.findBreakPointActualLocations(breakId);
if (!locations.length)
@@ -198,13 +199,12 @@
Debug.clearBreakOnUncaughtException();
}
-DebuggerScript.currentCallFrame = function(execState, args)
+DebuggerScript.currentCallFrame = function(execState, maximumLimit)
{
var frameCount = execState.frameCount();
- if (frameCount === 0)
- return undefined;
-
- var topFrame;
+ if (maximumLimit >= 0 && 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);
diff --git a/Source/bindings/v8/Dictionary.cpp b/Source/bindings/v8/Dictionary.cpp
index b95bed2..a25d7fa 100644
--- a/Source/bindings/v8/Dictionary.cpp
+++ b/Source/bindings/v8/Dictionary.cpp
@@ -110,6 +110,11 @@
return true;
}
+bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const
+{
+ return getKey(key, value);
+}
+
bool Dictionary::get(const String& key, bool& value) const
{
v8::Local<v8::Value> v8Value;
diff --git a/Source/bindings/v8/Dictionary.h b/Source/bindings/v8/Dictionary.h
index 47e12c4..b105017 100644
--- a/Source/bindings/v8/Dictionary.h
+++ b/Source/bindings/v8/Dictionary.h
@@ -94,6 +94,7 @@
bool get(const String&, RefPtr<CSSFontFaceRule>&) const;
bool get(const String&, RefPtr<DOMError>&) const;
bool get(const String&, RefPtr<VoidCallback>&) const;
+ bool get(const String&, v8::Local<v8::Value>&) const;
bool getOwnPropertiesAsStringHashMap(HashMap<String, String>&) const;
bool getOwnPropertyNames(Vector<String>&) const;
diff --git a/Source/bindings/v8/ExceptionState.cpp b/Source/bindings/v8/ExceptionState.cpp
new file mode 100644
index 0000000..1fdb4f8
--- /dev/null
+++ b/Source/bindings/v8/ExceptionState.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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/ExceptionState.h"
+
+#include "bindings/v8/V8ThrowException.h"
+#include "core/dom/ExceptionCode.h"
+
+namespace WebCore {
+
+void ExceptionState::clearException()
+{
+ m_code = 0;
+ m_exception.clear();
+}
+
+void ExceptionState::throwDOMException(const ExceptionCode& ec, const char* message)
+{
+ ASSERT(ec);
+ m_code = ec;
+ setException(V8ThrowException::createDOMException(ec, message, m_isolate));
+}
+
+void ExceptionState::setException(v8::Handle<v8::Value> exception)
+{
+ if (exception.IsEmpty()) {
+ clearException();
+ return;
+ }
+
+ m_exception.set(m_isolate, exception);
+}
+
+void ExceptionState::throwTypeError(const char* message)
+{
+ m_code = TypeError;
+ setException(V8ThrowException::createTypeError(message, m_isolate));
+}
+
+NonThrowExceptionState::NonThrowExceptionState()
+ : ExceptionState(0) { }
+
+void NonThrowExceptionState::throwDOMException(const ExceptionCode& ec, const char*)
+{
+ m_code = ec;
+}
+
+void NonThrowExceptionState::throwTypeError(const char*)
+{
+ m_code = TypeError;
+}
+
+} // namespace WebCore
diff --git a/Source/bindings/v8/ExceptionState.h b/Source/bindings/v8/ExceptionState.h
new file mode 100644
index 0000000..3f0de2d
--- /dev/null
+++ b/Source/bindings/v8/ExceptionState.h
@@ -0,0 +1,102 @@
+/*
+ * 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 ExceptionState_h
+#define ExceptionState_h
+
+#include "bindings/v8/ScopedPersistent.h"
+#include "bindings/v8/V8ThrowException.h"
+#include "wtf/Noncopyable.h"
+#include <v8.h>
+
+namespace WebCore {
+
+typedef int ExceptionCode;
+
+class ExceptionState {
+ WTF_MAKE_NONCOPYABLE(ExceptionState);
+public:
+ explicit ExceptionState(v8::Isolate* isolate)
+ : m_code(0)
+ , m_isolate(isolate) { }
+
+ virtual void throwDOMException(const ExceptionCode&, const char* message = 0);
+ virtual void throwTypeError(const char* message = 0);
+
+ bool hadException() const { return !m_exception.isEmpty() || m_code; }
+ void clearException();
+
+ bool throwIfNeeded()
+ {
+ if (m_exception.isEmpty()) {
+ if (!m_code)
+ return false;
+ throwDOMException(m_code);
+ }
+
+ V8ThrowException::throwError(m_exception.get());
+ return true;
+ }
+
+ // FIXME: Remove the rest of the public methods/operators once the transition is done.
+ typedef void* ExceptionState::*UnspecifiedBoolType;
+ operator UnspecifiedBoolType*() const
+ {
+ return m_code ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0;
+ }
+
+ operator ExceptionCode& () { return m_code; }
+
+ ExceptionState& operator=(const ExceptionCode& ec)
+ {
+ throwDOMException(ec);
+ return *this;
+ }
+
+protected:
+ ExceptionCode m_code;
+
+private:
+ void setException(v8::Handle<v8::Value>);
+
+ ScopedPersistent<v8::Value> m_exception;
+ v8::Isolate* m_isolate;
+};
+
+class NonThrowExceptionState : public ExceptionState {
+public:
+ NonThrowExceptionState();
+ virtual void throwDOMException(const ExceptionCode&, const char* = 0) OVERRIDE FINAL;
+ virtual void throwTypeError(const char* = 0) OVERRIDE FINAL;
+};
+
+} // namespace WebCore
+
+#endif // ExceptionState_h
diff --git a/Source/bindings/v8/V8CustomElementCallback.h b/Source/bindings/v8/ExceptionStatePlaceholder.cpp
similarity index 65%
copy from Source/bindings/v8/V8CustomElementCallback.h
copy to Source/bindings/v8/ExceptionStatePlaceholder.cpp
index 24becc1..352ba00 100644
--- a/Source/bindings/v8/V8CustomElementCallback.h
+++ b/Source/bindings/v8/ExceptionStatePlaceholder.cpp
@@ -28,35 +28,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef V8CustomElementCallback_h
-#define V8CustomElementCallback_h
-
-#include "bindings/v8/ActiveDOMCallback.h"
-#include "bindings/v8/DOMWrapperWorld.h"
-#include "bindings/v8/ScopedPersistent.h"
-#include "core/dom/CustomElementCallback.h"
-#include <v8.h>
+#include "config.h"
+#include "bindings/v8/ExceptionStatePlaceholder.h"
namespace WebCore {
-class Element;
-class ScriptExecutionContext;
+#if !ASSERT_DISABLED
-class V8CustomElementCallback : public CustomElementCallback, ActiveDOMCallback {
-public:
- static PassRefPtr<V8CustomElementCallback> create(ScriptExecutionContext*, v8::Handle<v8::Object> owner, v8::Handle<v8::Function> ready);
+NoExceptionStateAssertionChecker::NoExceptionStateAssertionChecker(const char* file, int line)
+ : ExceptionState(0)
+ , m_file(file)
+ , m_line(line) { }
- virtual ~V8CustomElementCallback() { }
-
-private:
- V8CustomElementCallback(ScriptExecutionContext*, v8::Handle<v8::Function> ready);
-
- virtual void ready(Element*) OVERRIDE;
-
- RefPtr<DOMWrapperWorld> m_world;
- ScopedPersistent<v8::Function> m_ready;
-};
-
+void NoExceptionStateAssertionChecker::throwDOMException(const ExceptionCode&, const char*)
+{
+ ASSERT_AT(false, m_file, m_line, "");
}
-#endif // CustomElementCallback_h
+void NoExceptionStateAssertionChecker::throwTypeError(const char*)
+{
+ ASSERT_AT(false, m_file, m_line, "");
+}
+
+#endif
+
+} // namespace WebCore
diff --git a/Source/bindings/v8/ExceptionStatePlaceholder.h b/Source/bindings/v8/ExceptionStatePlaceholder.h
new file mode 100644
index 0000000..8a94c53
--- /dev/null
+++ b/Source/bindings/v8/ExceptionStatePlaceholder.h
@@ -0,0 +1,75 @@
+/*
+ * 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 ExceptionStatePlaceholder_h
+#define ExceptionStatePlaceholder_h
+
+#include "bindings/v8/ExceptionState.h"
+#include "wtf/Assertions.h"
+
+namespace WebCore {
+
+class ExceptionState;
+
+class IgnorableExceptionState : public ExceptionState {
+public:
+ IgnorableExceptionState(): ExceptionState(0) { }
+ ExceptionState& returnThis() { return *this; }
+ virtual void throwDOMException(const ExceptionCode&, const char* message = 0) OVERRIDE FINAL { };
+ virtual void throwTypeError(const char* message = 0) OVERRIDE FINAL { }
+};
+
+#define IGNORE_EXCEPTION_STATE (::WebCore::IgnorableExceptionState().returnThis())
+
+#if ASSERT_DISABLED
+
+#define ASSERT_NO_EXCEPTION_STATE (::WebCore::IgnorableExceptionState().returnThis())
+
+#else
+
+class NoExceptionStateAssertionChecker : public ExceptionState {
+public:
+ NoExceptionStateAssertionChecker(const char* file, int line);
+ ExceptionState& returnThis() { return *this; }
+ virtual void throwDOMException(const ExceptionCode&, const char* message = 0) OVERRIDE FINAL;
+ virtual void throwTypeError(const char* message = 0) OVERRIDE FINAL;
+
+private:
+ const char* m_file;
+ int m_line;
+};
+
+#define ASSERT_NO_EXCEPTION_STATE (::WebCore::NoExceptionStateAssertionChecker(__FILE__, __LINE__).returnThis())
+
+#endif
+
+} // namespace WebCore
+
+#endif // ExceptionStatePlaceholder_h
diff --git a/Source/bindings/v8/NPV8Object.cpp b/Source/bindings/v8/NPV8Object.cpp
index 59017b5..621a99c 100644
--- a/Source/bindings/v8/NPV8Object.cpp
+++ b/Source/bindings/v8/NPV8Object.cpp
@@ -87,12 +87,12 @@
return ScriptController::mainWorldContext(object->rootObject->frame());
}
-static PassOwnArrayPtr<v8::Handle<v8::Value> > createValueListFromVariantArgs(const NPVariant* arguments, uint32_t argumentCount, NPP owner, v8::Isolate* isolate)
+static PassOwnArrayPtr<v8::Handle<v8::Value> > createValueListFromVariantArgs(const NPVariant* arguments, uint32_t argumentCount, NPObject* owner, v8::Isolate* isolate)
{
OwnArrayPtr<v8::Handle<v8::Value> > argv = adoptArrayPtr(new v8::Handle<v8::Value>[argumentCount]);
for (uint32_t index = 0; index < argumentCount; index++) {
const NPVariant* arg = &arguments[index];
- argv[index] = convertNPVariantToV8Object(arg, isolate);
+ argv[index] = convertNPVariantToV8Object(arg, owner, isolate);
}
return argv.release();
}
@@ -257,7 +257,7 @@
// Call the function object.
v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(functionObject);
- OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npp, isolate);
+ OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate);
v8::Local<v8::Value> resultObject = frame->script()->callFunction(function, v8Object, argumentCount, argv.get());
// If we had an error, return false. The spec is a little unclear here, but says "Returns true if the method was
@@ -265,9 +265,7 @@
if (resultObject.IsEmpty())
return false;
- // If the returned object isn't yet owned then it must have the same owner
- // as the frame.
- convertV8ObjectToNPVariant(resultObject, frame->script()->frameNPP(), result);
+ convertV8ObjectToNPVariant(resultObject, npObject, result);
return true;
}
@@ -303,13 +301,13 @@
if (!functionObject->IsFunction())
return false;
- Frame* frame = v8NpObject->rootObject->frame();
- ASSERT(frame);
-
v8::Local<v8::Value> resultObject;
v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(functionObject);
if (!function->IsNull()) {
- OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npp, isolate);
+ Frame* frame = v8NpObject->rootObject->frame();
+ ASSERT(frame);
+
+ OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate);
resultObject = frame->script()->callFunction(function, functionObject, argumentCount, argv.get());
}
// If we had an error, return false. The spec is a little unclear here, but says "Returns true if the method was
@@ -317,9 +315,7 @@
if (resultObject.IsEmpty())
return false;
- // If the returned object isn't yet owned then it must have the same owner
- // as the frame.
- convertV8ObjectToNPVariant(resultObject, frame->script()->frameNPP(), result);
+ convertV8ObjectToNPVariant(resultObject, npObject, result);
return true;
}
@@ -365,7 +361,7 @@
return false;
if (_NPN_IsAlive(npObject))
- convertV8ObjectToNPVariant(v8result, frame->script()->frameNPP(), result);
+ convertV8ObjectToNPVariant(v8result, npObject, result);
return true;
}
@@ -390,10 +386,7 @@
if (v8result.IsEmpty())
return false;
- Frame* frame = object->rootObject->frame();
- ASSERT(frame);
-
- convertV8ObjectToNPVariant(v8result, frame->script()->frameNPP(), result);
+ convertV8ObjectToNPVariant(v8result, npObject, result);
return true;
}
@@ -422,7 +415,7 @@
ExceptionCatcher exceptionCatcher;
v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object);
- obj->Set(npIdentifierToV8Identifier(propertyName), convertNPVariantToV8Object(value, context->GetIsolate()));
+ obj->Set(npIdentifierToV8Identifier(propertyName), convertNPVariantToV8Object(value, object->rootObject->frame()->script()->windowScriptNPObject(), context->GetIsolate()));
return true;
}
@@ -597,21 +590,20 @@
if (!ctorObj->IsFunction())
return false;
- Frame* frame = object->rootObject->frame();
- ASSERT(frame);
-
// Call the constructor.
v8::Local<v8::Value> resultObject;
v8::Handle<v8::Function> ctor = v8::Handle<v8::Function>::Cast(ctorObj);
if (!ctor->IsNull()) {
- OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npp, isolate);
+ Frame* frame = object->rootObject->frame();
+ ASSERT(frame);
+ OwnArrayPtr<v8::Handle<v8::Value> > argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate);
resultObject = V8ObjectConstructor::newInstanceInDocument(ctor, argumentCount, argv.get(), frame ? frame->document() : 0);
}
if (resultObject.IsEmpty())
return false;
- convertV8ObjectToNPVariant(resultObject, frame->script()->frameNPP(), result);
+ convertV8ObjectToNPVariant(resultObject, npObject, result);
return true;
}
diff --git a/Source/bindings/v8/ScriptController.cpp b/Source/bindings/v8/ScriptController.cpp
index d0085c4..601214d 100644
--- a/Source/bindings/v8/ScriptController.cpp
+++ b/Source/bindings/v8/ScriptController.cpp
@@ -100,17 +100,17 @@
ScriptController::~ScriptController()
{
clearForClose(true);
-
- if (m_frameNPP) {
- _NPN_UnregisterObjectOwner(m_frameNPP.get());
- m_frameNPP.clear();
- }
-
- ASSERT(m_pluginNPPs.isEmpty());
}
void ScriptController::clearScriptObjects()
{
+ PluginObjectMap::iterator it = m_pluginObjects.begin();
+ for (; it != m_pluginObjects.end(); ++it) {
+ _NPN_UnregisterObject(it->value);
+ _NPN_ReleaseObject(it->value);
+ }
+ m_pluginObjects.clear();
+
if (m_windowScriptNPObject) {
// Dispose of the underlying V8 object before releasing our reference
// to it, so that if a plugin fails to release it properly we will
@@ -354,7 +354,7 @@
v8::Context::Scope scope(v8Context);
- v8::Handle<v8::Object> value = createV8ObjectForNPObject(object);
+ v8::Handle<v8::Object> value = createV8ObjectForNPObject(object, 0);
// Attach to the global object.
v8::Handle<v8::Object> global = v8Context->Global();
@@ -414,33 +414,22 @@
// NPObject as part of its wrapper. However, before accessing the object
// it must consult the _NPN_Registry.
- // Create the plugin script object, registered against the plugin.
- v8::Local<v8::Object> wrapper = createV8ObjectForNPObject(npObject);
+ v8::Local<v8::Object> wrapper = createV8ObjectForNPObject(npObject, 0);
- // We were passed a reference to the object, so release it.
- _NPN_ReleaseObject(npObject);
+ // Track the plugin object. We've been given a reference to the object.
+ m_pluginObjects.set(widget, npObject);
return V8ScriptInstance::create(wrapper);
}
-void ScriptController::allowScriptObjectsForPlugin(Widget* widget)
+void ScriptController::cleanupScriptObjectsForPlugin(Widget* nativeHandle)
{
- ASSERT(widget->isPluginView());
- ASSERT(toPluginView(widget)->pluginNPP());
-
- // Register the plugin as an object owner.
- _NPN_RegisterObjectOwner(toPluginView(widget)->pluginNPP());
- m_pluginNPPs.add(toPluginView(widget)->pluginNPP());
-}
-
-void ScriptController::cleanupScriptObjectsForPlugin(Widget* widget)
-{
- ASSERT(widget->isPluginView());
- NPP instance = toPluginView(widget)->pluginNPP();
- if (m_pluginNPPs.find(instance) == m_pluginNPPs.end())
+ PluginObjectMap::iterator it = m_pluginObjects.find(nativeHandle);
+ if (it == m_pluginObjects.end())
return;
- _NPN_UnregisterObjectOwner(instance);
- m_pluginNPPs.remove(instance);
+ _NPN_UnregisterObject(it->value);
+ _NPN_ReleaseObject(it->value);
+ m_pluginObjects.remove(it);
}
V8Extensions& ScriptController::registeredExtensions()
@@ -466,19 +455,19 @@
return 0;
}
-NPObject* ScriptController::createScriptObjectForFrame()
+static NPObject* createScriptObject(Frame* frame)
{
v8::HandleScope handleScope;
- v8::Handle<v8::Context> v8Context = ScriptController::mainWorldContext(m_frame);
+ v8::Handle<v8::Context> v8Context = ScriptController::mainWorldContext(frame);
if (v8Context.IsEmpty())
return createNoScriptObject();
v8::Context::Scope scope(v8Context);
- DOMWindow* window = m_frame->document()->domWindow();
+ DOMWindow* window = frame->document()->domWindow();
v8::Handle<v8::Value> global = toV8(window, v8::Handle<v8::Object>(), v8Context->GetIsolate());
ASSERT(global->IsObject());
- return npCreateV8ScriptObject(frameNPP(), v8::Handle<v8::Object>::Cast(global), window);
+ return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(global), window);
}
NPObject* ScriptController::windowScriptNPObject()
@@ -489,7 +478,8 @@
if (canExecuteScripts(NotAboutToExecuteScript)) {
// JavaScript is enabled, so there is a JavaScript window object.
// Return an NPObject bound to the window object.
- m_windowScriptNPObject = createScriptObjectForFrame();
+ m_windowScriptNPObject = createScriptObject(m_frame);
+ _NPN_RegisterObject(m_windowScriptNPObject, 0);
} else {
// JavaScript is not enabled, so we cannot bind the NPObject to the
// JavaScript window object. Instead, we create an NPObject of a
@@ -499,15 +489,6 @@
return m_windowScriptNPObject;
}
-NPP ScriptController::frameNPP()
-{
- if (!m_frameNPP) {
- m_frameNPP = adoptPtr(new NPP_t);
- _NPN_RegisterObjectOwner(m_frameNPP.get());
- }
- return m_frameNPP.get();
-}
-
NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement* plugin)
{
// Can't create NPObjects when JavaScript is disabled.
@@ -525,7 +506,7 @@
if (!v8plugin->IsObject())
return createNoScriptObject();
- return npCreateV8ScriptObject(frameNPP(), v8::Handle<v8::Object>::Cast(v8plugin), window);
+ return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(v8plugin), window);
}
void ScriptController::clearWindowShell()
diff --git a/Source/bindings/v8/ScriptController.h b/Source/bindings/v8/ScriptController.h
index e407666..a2bd844 100644
--- a/Source/bindings/v8/ScriptController.h
+++ b/Source/bindings/v8/ScriptController.h
@@ -33,16 +33,16 @@
#include "bindings/v8/ScriptInstance.h"
#include "bindings/v8/ScriptValue.h"
-#include <bindings/npruntime.h>
#include <v8.h>
#include "wtf/Forward.h"
#include "wtf/HashMap.h"
-#include "wtf/HashSet.h"
#include "wtf/RefCounted.h"
#include "wtf/Vector.h"
#include "wtf/text/TextPosition.h"
+struct NPObject;
+
namespace WebCore {
class DOMWrapperWorld;
@@ -64,6 +64,10 @@
NotAboutToExecuteScript
};
+enum IsolatedWorldConstants {
+ EmbedderWorldIdLimit = (1 << 29)
+};
+
class ScriptController {
public:
ScriptController(Frame*);
@@ -141,7 +145,6 @@
void updateSecurityOrigin();
void clearScriptObjects();
- void allowScriptObjectsForPlugin(Widget*);
void cleanupScriptObjectsForPlugin(Widget*);
void clearForClose();
@@ -149,7 +152,6 @@
NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*);
NPObject* windowScriptNPObject();
- NPP frameNPP();
// Registers a v8 extension to be available on webpages. Will only
// affect v8 contexts initialized after this call. Takes ownership of
@@ -162,8 +164,8 @@
private:
typedef HashMap<int, OwnPtr<V8WindowShell> > IsolatedWorldMap;
+ typedef HashMap<Widget*, NPObject*> PluginObjectMap;
- NPObject* createScriptObjectForFrame();
void clearForClose(bool destroyGlobal);
Frame* m_frame;
@@ -175,11 +177,13 @@
bool m_paused;
- NPObject* m_windowScriptNPObject;
- OwnPtr<NPP_t> m_frameNPP;
+ // A mapping between Widgets and their corresponding script object.
+ // This list is used so that when the plugin dies, we can immediately
+ // invalidate all sub-objects which are associated with that plugin.
+ // The frame keeps a NPObject reference for each item on the list.
+ PluginObjectMap m_pluginObjects;
- typedef HashSet<NPP> PluginInstances;
- PluginInstances m_pluginNPPs;
+ NPObject* m_windowScriptNPObject;
};
} // namespace WebCore
diff --git a/Source/bindings/v8/ScriptDebugServer.cpp b/Source/bindings/v8/ScriptDebugServer.cpp
index 0b23f20..077f83a 100644
--- a/Source/bindings/v8/ScriptDebugServer.cpp
+++ b/Source/bindings/v8/ScriptDebugServer.cpp
@@ -136,7 +136,7 @@
{
}
-String ScriptDebugServer::setBreakpoint(const String& sourceID, const ScriptBreakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber)
+String ScriptDebugServer::setBreakpoint(const String& sourceID, const ScriptBreakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber, bool interstatementLocation)
{
v8::HandleScope scope;
v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext();
@@ -146,6 +146,7 @@
args->Set(v8::String::NewSymbol("sourceID"), v8String(sourceID, debuggerContext->GetIsolate()));
args->Set(v8::String::NewSymbol("lineNumber"), v8::Integer::New(scriptBreakpoint.lineNumber, debuggerContext->GetIsolate()));
args->Set(v8::String::NewSymbol("columnNumber"), v8::Integer::New(scriptBreakpoint.columnNumber, debuggerContext->GetIsolate()));
+ args->Set(v8::String::NewSymbol("interstatementLocation"), v8Boolean(interstatementLocation, debuggerContext->GetIsolate()));
args->Set(v8::String::NewSymbol("condition"), v8String(scriptBreakpoint.condition, debuggerContext->GetIsolate()));
v8::Handle<v8::Function> setBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8::String::NewSymbol("setBreakpoint")));
@@ -373,18 +374,24 @@
m_scriptPreprocessor = adoptPtr(new ScriptPreprocessor(preprocessorBody, m_isolate));
}
+PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::wrapCallFrames(v8::Handle<v8::Object> executionState, int maximumLimit)
+{
+ v8::Handle<v8::Value> argv[] = { executionState, v8::Integer::New(maximumLimit) };
+ v8::Handle<v8::Value> currentCallFrameV8 = callDebuggerMethod("currentCallFrame", 2, argv);
+
+ ASSERT(!currentCallFrameV8.IsEmpty());
+ if (!currentCallFrameV8->IsObject())
+ return PassRefPtr<JavaScriptCallFrame>();
+ return JavaScriptCallFrame::create(v8::Debug::GetDebugContext(), v8::Handle<v8::Object>::Cast(currentCallFrameV8));
+}
+
ScriptValue ScriptDebugServer::currentCallFrame()
{
ASSERT(isPaused());
v8::HandleScope handleScope(m_isolate);
- v8::Handle<v8::Value> argv[] = { m_executionState.newLocal(m_isolate) };
- v8::Handle<v8::Value> currentCallFrameV8 = callDebuggerMethod("currentCallFrame", 1, argv);
-
- ASSERT(!currentCallFrameV8.IsEmpty());
- if (!currentCallFrameV8->IsObject())
+ RefPtr<JavaScriptCallFrame> currentCallFrame = wrapCallFrames(m_executionState.newLocal(m_isolate), -1);
+ if (!currentCallFrame)
return ScriptValue(v8::Null());
-
- RefPtr<JavaScriptCallFrame> currentCallFrame = JavaScriptCallFrame::create(v8::Debug::GetDebugContext(), v8::Handle<v8::Object>::Cast(currentCallFrameV8));
v8::Context::Scope contextScope(m_pausedContext);
return ScriptValue(toV8(currentCallFrame.release(), v8::Handle<v8::Object>(), m_pausedContext->GetIsolate()));
}
@@ -412,10 +419,10 @@
ScriptDebugServer* thisPtr = toScriptDebugServer(args.Data());
v8::Handle<v8::Value> exception;
v8::Handle<v8::Array> hitBreakpoints;
- thisPtr->breakProgram(v8::Handle<v8::Object>::Cast(args[0]), exception, hitBreakpoints);
+ thisPtr->handleProgramBreak(v8::Handle<v8::Object>::Cast(args[0]), exception, hitBreakpoints);
}
-void ScriptDebugServer::breakProgram(v8::Handle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers)
+void ScriptDebugServer::handleProgramBreak(v8::Handle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers)
{
// Don't allow nested breaks.
if (isPaused())
@@ -441,10 +448,10 @@
m_runningNestedMessageLoop = false;
}
-void ScriptDebugServer::breakProgram(const v8::Debug::EventDetails& eventDetails, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers)
+void ScriptDebugServer::handleProgramBreak(const v8::Debug::EventDetails& eventDetails, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers)
{
m_pausedContext = eventDetails.GetEventContext();
- breakProgram(eventDetails.GetExecutionState(), exception, hitBreakpointNumbers);
+ handleProgramBreak(eventDetails.GetExecutionState(), exception, hitBreakpointNumbers);
m_pausedContext.Clear();
}
@@ -508,18 +515,23 @@
// 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 (topFrame && listener->shouldSkipPause(topFrame)) {
+ // Silently continue on this break.
+ return;
+ }
v8::Handle<v8::Object> eventData = eventDetails.GetEventData();
v8::Handle<v8::Value> exceptionGetterValue = eventData->Get(v8::String::NewSymbol("exception"));
ASSERT(!exceptionGetterValue.IsEmpty() && exceptionGetterValue->IsFunction());
v8::Handle<v8::Value> exception = V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function>::Cast(exceptionGetterValue), eventData, 0, 0, m_isolate);
- breakProgram(eventDetails, exception, v8::Handle<v8::Array>());
+ handleProgramBreak(eventDetails, exception, v8::Handle<v8::Array>());
} else if (event == v8::Break) {
v8::Handle<v8::Function> getBreakpointNumbersFunction = v8::Local<v8::Function>::Cast(debuggerScript->Get(v8::String::NewSymbol("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());
- breakProgram(eventDetails, v8::Handle<v8::Value>(), hitBreakpoints.As<v8::Array>());
+ handleProgramBreak(eventDetails, v8::Handle<v8::Value>(), hitBreakpoints.As<v8::Array>());
}
}
}
diff --git a/Source/bindings/v8/ScriptDebugServer.h b/Source/bindings/v8/ScriptDebugServer.h
index 3a6798b..dd8189e 100644
--- a/Source/bindings/v8/ScriptDebugServer.h
+++ b/Source/bindings/v8/ScriptDebugServer.h
@@ -49,11 +49,12 @@
class ScriptObject;
class ScriptState;
class ScriptValue;
+class JavaScriptCallFrame;
class ScriptDebugServer {
WTF_MAKE_NONCOPYABLE(ScriptDebugServer);
public:
- String setBreakpoint(const String& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber);
+ String setBreakpoint(const String& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber, bool interstatementLocation);
void removeBreakpoint(const String& breakpointId);
void clearBreakpoints();
void setBreakpointsActivated(bool activated);
@@ -110,8 +111,8 @@
virtual void quitMessageLoopOnPause() = 0;
static void breakProgramCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
- void breakProgram(v8::Handle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpoints);
- void breakProgram(const v8::Debug::EventDetails&, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers);
+ 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);
static void v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails);
void handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails);
@@ -134,6 +135,8 @@
v8::Isolate* m_isolate;
private:
+ PassRefPtr<JavaScriptCallFrame> wrapCallFrames(v8::Handle<v8::Object> executionState, int maximumLimit);
+
class ScriptPreprocessor;
OwnPtr<ScriptPreprocessor> m_scriptPreprocessor;
bool m_runningNestedMessageLoop;
diff --git a/Source/bindings/v8/ScriptProfiler.cpp b/Source/bindings/v8/ScriptProfiler.cpp
index fca8197..f152935 100644
--- a/Source/bindings/v8/ScriptProfiler.cpp
+++ b/Source/bindings/v8/ScriptProfiler.cpp
@@ -286,7 +286,7 @@
// 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(V8Node::HasInstance(*wrapper, m_isolate, worldType(m_isolate)));
+ ASSERT(V8Node::HasInstanceInAnyWorld(*wrapper, m_isolate));
ASSERT((*wrapper)->IsObject());
m_visitor->visitNode(V8Node::toNative(*wrapper));
}
diff --git a/Source/bindings/v8/ScriptPromiseResolver.cpp b/Source/bindings/v8/ScriptPromiseResolver.cpp
new file mode 100644
index 0000000..77f4d27
--- /dev/null
+++ b/Source/bindings/v8/ScriptPromiseResolver.cpp
@@ -0,0 +1,155 @@
+/*
+ * 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/ScriptPromiseResolver.h"
+
+#include "RuntimeEnabledFeatures.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 "wtf/MainThread.h"
+
+#include <v8.h>
+
+namespace WebCore {
+
+ScriptPromiseResolver::ScriptPromiseResolver(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
+{
+ ASSERT(RuntimeEnabledFeatures::promiseEnabled());
+ v8::Local<v8::Object> promise, resolver;
+ V8PromiseCustom::createPromise(creationContext, &promise, &resolver, isolate);
+ m_promise.set(isolate, promise);
+ m_resolver.set(isolate, resolver);
+}
+
+ScriptPromiseResolver::~ScriptPromiseResolver()
+{
+ detach();
+}
+
+PassRefPtr<ScriptPromiseResolver> ScriptPromiseResolver::create(ScriptExecutionContext* context)
+{
+ ASSERT(isMainThread());
+ ASSERT(context);
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope scope(isolate);
+ return adoptRef(new ScriptPromiseResolver(toV8Context(context, DOMWrapperWorld::current())->Global(), isolate));
+}
+
+PassRefPtr<ScriptPromiseResolver> ScriptPromiseResolver::create()
+{
+ ASSERT(isMainThread());
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope scope(isolate);
+ return adoptRef(new ScriptPromiseResolver(v8::Object::New(), isolate));
+}
+
+bool ScriptPromiseResolver::isPending() const
+{
+ ASSERT(isMainThread());
+ v8::HandleScope scope(v8::Isolate::GetCurrent());
+ return isPendingInternal();
+}
+
+void ScriptPromiseResolver::detach()
+{
+ ASSERT(isMainThread());
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope scope(isolate);
+ detachPromise();
+ reject(v8::Undefined(isolate), isolate);
+ m_resolver.clear();
+}
+
+void ScriptPromiseResolver::fulfill(v8::Handle<v8::Value> value, v8::Isolate* isolate)
+{
+ ASSERT(isMainThread());
+ if (!isPendingInternal())
+ return;
+ V8PromiseCustom::fulfillResolver(m_resolver.get(), value, V8PromiseCustom::Asynchronous, isolate);
+ m_resolver.clear();
+}
+
+void ScriptPromiseResolver::resolve(v8::Handle<v8::Value> value, v8::Isolate* isolate)
+{
+ ASSERT(isMainThread());
+ if (!isPendingInternal())
+ return;
+ V8PromiseCustom::resolveResolver(m_resolver.get(), value, V8PromiseCustom::Asynchronous, isolate);
+ m_resolver.clear();
+}
+
+void ScriptPromiseResolver::reject(v8::Handle<v8::Value> value, v8::Isolate* isolate)
+{
+ ASSERT(isMainThread());
+ if (!isPendingInternal())
+ return;
+ V8PromiseCustom::rejectResolver(m_resolver.get(), value, V8PromiseCustom::Asynchronous, isolate);
+ m_resolver.clear();
+}
+
+void ScriptPromiseResolver::fulfill(ScriptValue value)
+{
+ ASSERT(isMainThread());
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope scope(isolate);
+ fulfill(value.v8Value(), isolate);
+}
+
+void ScriptPromiseResolver::resolve(ScriptValue value)
+{
+ ASSERT(isMainThread());
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope scope(isolate);
+ resolve(value.v8Value(), isolate);
+}
+
+void ScriptPromiseResolver::reject(ScriptValue value)
+{
+ ASSERT(isMainThread());
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope scope(isolate);
+ reject(value.v8Value(), isolate);
+}
+
+bool ScriptPromiseResolver::isPendingInternal() const
+{
+ ASSERT(isMainThread());
+ if (m_resolver.isEmpty() || V8PromiseCustom::isInternalDetached(m_resolver.get()))
+ return false;
+ v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(m_resolver.get());
+ V8PromiseCustom::PromiseState state = V8PromiseCustom::getState(internal);
+ return state == V8PromiseCustom::Pending;
+}
+
+} // namespace WebCore
diff --git a/Source/bindings/v8/ScriptPromiseResolver.h b/Source/bindings/v8/ScriptPromiseResolver.h
new file mode 100644
index 0000000..ed0f66d
--- /dev/null
+++ b/Source/bindings/v8/ScriptPromiseResolver.h
@@ -0,0 +1,134 @@
+/*
+ * 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 ScriptPromiseResolver_h
+#define ScriptPromiseResolver_h
+
+#include "bindings/v8/ScopedPersistent.h"
+#include "bindings/v8/ScriptObject.h"
+#include "bindings/v8/ScriptState.h"
+#include "bindings/v8/ScriptValue.h"
+#include "wtf/MainThread.h"
+#include "wtf/RefPtr.h"
+
+#include <v8.h>
+
+namespace WebCore {
+
+class ScriptExecutionContext;
+
+// ScriptPromiseResolver is a class for accessing PromiseResolver methods
+// (fulfill / resolve / reject) from C++ world.
+// ScriptPromiseResolver holds a Promise and a PromiseResolver.
+// All methods of this class must be called from the main thread.
+// Here is a typical usage:
+// 1. Create a ScriptPromiseResolver.
+// 2. Pass the promise object of the holder to a JavaScript program
+// (such as XMLHttpRequest return value).
+// 3. Detach the promise object if you no long need it.
+// 4. Call fullfill or reject when the operation completes or
+// the operation fails respectively.
+class ScriptPromiseResolver : public RefCounted<ScriptPromiseResolver> {
+ WTF_MAKE_NONCOPYABLE(ScriptPromiseResolver);
+public:
+ static PassRefPtr<ScriptPromiseResolver> create(ScriptExecutionContext*);
+ static PassRefPtr<ScriptPromiseResolver> create();
+ ~ScriptPromiseResolver();
+
+ // Detach the promise object and reject the resolver object with undefined.
+ void detach();
+
+ // Detach the promise object.
+ void detachPromise() { m_promise.clear(); }
+
+ // Return true if the following conditions are met:
+ // - The resolver object is not detached.
+ // - The resolver's promise object is in pending state.
+ // - The resolver's resolved flag is not set.
+ bool isPending() const;
+
+ ScriptObject promise() { return ScriptObject(ScriptState::current(), m_promise.get()); }
+
+ // Fulfill with a C++ object which can be converted to a v8 object by toV8.
+ template<typename T>
+ inline void fulfill(PassRefPtr<T>);
+ // Resolve with a C++ object which can be converted to a v8 object by toV8.
+ template<typename T>
+ inline void resolve(PassRefPtr<T>);
+ // Reject with a C++ object which can be converted to a v8 object by toV8.
+ template<typename T>
+ inline void reject(PassRefPtr<T>);
+
+ void fulfill(ScriptValue);
+ void resolve(ScriptValue);
+ void reject(ScriptValue);
+
+private:
+ ScriptPromiseResolver(v8::Handle<v8::Object> creationContext, v8::Isolate*);
+ void fulfill(v8::Handle<v8::Value>, v8::Isolate*);
+ void resolve(v8::Handle<v8::Value>, v8::Isolate*);
+ void reject(v8::Handle<v8::Value>, v8::Isolate*);
+
+ ScopedPersistent<v8::Object> m_promise;
+ ScopedPersistent<v8::Object> m_resolver;
+ bool isPendingInternal() const;
+};
+
+template<typename T>
+void ScriptPromiseResolver::fulfill(PassRefPtr<T> value)
+{
+ ASSERT(isMainThread());
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope scope(isolate);
+ fulfill(toV8(value.get(), v8::Object::New(), isolate), isolate);
+}
+
+template<typename T>
+void ScriptPromiseResolver::resolve(PassRefPtr<T> value)
+{
+ ASSERT(isMainThread());
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope scope(isolate);
+ resolve(toV8(value.get(), v8::Object::New(), isolate), isolate);
+}
+
+template<typename T>
+void ScriptPromiseResolver::reject(PassRefPtr<T> value)
+{
+ ASSERT(isMainThread());
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope scope(isolate);
+ reject(toV8(value.get(), v8::Object::New(), isolate), isolate);
+}
+
+} // namespace WebCore
+
+
+#endif // ScriptPromiseResolver_h
diff --git a/Source/bindings/v8/ScriptPromiseResolverTest.cpp b/Source/bindings/v8/ScriptPromiseResolverTest.cpp
new file mode 100644
index 0000000..7053707
--- /dev/null
+++ b/Source/bindings/v8/ScriptPromiseResolverTest.cpp
@@ -0,0 +1,198 @@
+/*
+ * 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/ScriptPromiseResolver.h"
+
+#include "bindings/v8/V8Binding.h"
+#include "bindings/v8/custom/V8PromiseCustom.h"
+
+#include <gtest/gtest.h>
+#include <v8.h>
+
+namespace WebCore {
+
+namespace {
+
+class ScriptPromiseResolverTest : public testing::Test {
+public:
+ ScriptPromiseResolverTest() : m_scope(v8::Isolate::GetCurrent())
+ {
+ }
+
+ void SetUp()
+ {
+ m_isolate = v8::Isolate::GetCurrent();
+ m_context.set(m_isolate, v8::Context::New(m_isolate));
+ m_context.get()->Enter();
+ m_perContextData = V8PerContextData::create(m_context.get());
+ m_perContextData->init();
+ m_resolver = ScriptPromiseResolver::create();
+ m_promise = m_resolver->promise();
+ }
+
+ void TearDown()
+ {
+ m_resolver = 0;
+ m_promise.clear();
+ m_perContextData.clear();
+ m_context.get()->Exit();
+ }
+
+ V8PromiseCustom::PromiseState state()
+ {
+ return V8PromiseCustom::getState(V8PromiseCustom::getInternal(promise()));
+ }
+
+ v8::Local<v8::Value> result()
+ {
+ return V8PromiseCustom::getInternal(promise())->GetInternalField(V8PromiseCustom::InternalResultIndex);
+ }
+
+ v8::Local<v8::Object> promise()
+ {
+ ASSERT(!m_promise.hasNoValue());
+ return m_promise.v8Object();
+ }
+
+protected:
+ RefPtr<ScriptPromiseResolver> m_resolver;
+ ScriptObject m_promise;
+ v8::HandleScope m_scope;
+ OwnPtr<V8PerContextData> m_perContextData;
+ ScopedPersistent<v8::Context> m_context;
+ v8::Isolate* m_isolate;
+};
+
+TEST_F(ScriptPromiseResolverTest, initialState)
+{
+ EXPECT_TRUE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Pending, state());
+ EXPECT_TRUE(result()->IsUndefined());
+}
+
+TEST_F(ScriptPromiseResolverTest, fulfill)
+{
+ EXPECT_TRUE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Pending, state());
+ EXPECT_TRUE(result()->IsUndefined());
+
+ m_resolver->fulfill(ScriptValue(v8::Integer::New(3)));
+
+ EXPECT_FALSE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Fulfilled, state());
+ ASSERT_TRUE(result()->IsNumber());
+ EXPECT_EQ(3, result().As<v8::Integer>()->Value());
+}
+
+TEST_F(ScriptPromiseResolverTest, resolve)
+{
+ EXPECT_TRUE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Pending, state());
+ EXPECT_TRUE(result()->IsUndefined());
+
+ m_resolver->resolve(ScriptValue(v8::Integer::New(3)));
+
+ EXPECT_FALSE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Fulfilled, state());
+ ASSERT_TRUE(result()->IsNumber());
+ EXPECT_EQ(3, result().As<v8::Integer>()->Value());
+}
+
+TEST_F(ScriptPromiseResolverTest, reject)
+{
+ EXPECT_TRUE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Pending, state());
+ EXPECT_TRUE(result()->IsUndefined());
+
+ m_resolver->reject(ScriptValue(v8::Integer::New(3)));
+
+ EXPECT_FALSE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Rejected, state());
+ ASSERT_TRUE(result()->IsNumber());
+ EXPECT_EQ(3, result().As<v8::Integer>()->Value());
+}
+
+TEST_F(ScriptPromiseResolverTest, fulfillOverFulfill)
+{
+ EXPECT_TRUE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Pending, state());
+ EXPECT_TRUE(result()->IsUndefined());
+
+ m_resolver->fulfill(ScriptValue(v8::Integer::New(3)));
+
+ EXPECT_FALSE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Fulfilled, state());
+ ASSERT_TRUE(result()->IsNumber());
+ EXPECT_EQ(3, result().As<v8::Integer>()->Value());
+
+ m_resolver->fulfill(ScriptValue(v8::Integer::New(4)));
+ EXPECT_FALSE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Fulfilled, state());
+ ASSERT_TRUE(result()->IsNumber());
+ EXPECT_EQ(3, result().As<v8::Integer>()->Value());
+}
+
+TEST_F(ScriptPromiseResolverTest, rejectOverFulfill)
+{
+ EXPECT_TRUE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Pending, state());
+ EXPECT_TRUE(result()->IsUndefined());
+
+ m_resolver->fulfill(ScriptValue(v8::Integer::New(3)));
+
+ 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)));
+ EXPECT_FALSE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Fulfilled, state());
+ ASSERT_TRUE(result()->IsNumber());
+ EXPECT_EQ(3, result().As<v8::Integer>()->Value());
+}
+
+TEST_F(ScriptPromiseResolverTest, detach)
+{
+ EXPECT_TRUE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Pending, state());
+ EXPECT_TRUE(result()->IsUndefined());
+
+ m_resolver->detach();
+
+ EXPECT_FALSE(m_resolver->isPending());
+ EXPECT_EQ(V8PromiseCustom::Rejected, state());
+ EXPECT_TRUE(result()->IsUndefined());
+}
+
+} // namespace
+
+} // namespace WebCore
diff --git a/Source/bindings/v8/SerializedScriptValue.cpp b/Source/bindings/v8/SerializedScriptValue.cpp
index cdad44e..8f2a0f6 100644
--- a/Source/bindings/v8/SerializedScriptValue.cpp
+++ b/Source/bindings/v8/SerializedScriptValue.cpp
@@ -31,7 +31,6 @@
#include "config.h"
#include "bindings/v8/SerializedScriptValue.h"
-#include "V8ArrayBuffer.h"
#include "V8ArrayBufferView.h"
#include "V8Blob.h"
#include "V8DOMFileSystem.h"
@@ -682,13 +681,13 @@
return wrapper.As<v8::Object>();
}
-static v8::Handle<v8::Object> toV8Object(ArrayBuffer* impl, v8::Isolate* isolate)
+static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Isolate* isolate)
{
if (!impl)
- return v8::Handle<v8::Object>();
+ return v8::Handle<v8::ArrayBuffer>();
v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate);
- ASSERT(wrapper->IsObject());
- return wrapper.As<v8::Object>();
+ ASSERT(wrapper->IsArrayBuffer());
+ return wrapper.As<v8::ArrayBuffer>();
}
class Serializer {
@@ -846,7 +845,7 @@
protected:
virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
- StateBase* serializeProperties(bool ignoreIndexed, Serializer& serializer)
+ StateBase* serializeProperties(bool ignoreIndexed, Serializer& serializer)
{
m_isSerializingAccessor = false;
while (m_index < m_propertyNames->Length()) {
@@ -979,7 +978,7 @@
m_propertyNames = v8::Local<v8::Array>::New(propertyNames);
}
- virtual StateBase* advance(Serializer& serializer)
+ virtual StateBase* advance(Serializer& serializer)
{
return serializeProperties(false, serializer);
}
@@ -1178,7 +1177,7 @@
return 0;
}
- static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount)
+ static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount)
{
// Let K be the cost of serializing all property values that are there
// Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t key)
@@ -1700,7 +1699,7 @@
*value = v8::Number::New(number);
return true;
}
-
+
bool readNumberObject(v8::Handle<v8::Value>* value)
{
double number;
@@ -1772,7 +1771,7 @@
return false;
if (!creator.consumeTopOfStack(&arrayBufferV8Value))
return false;
- if (arrayBufferV8Value.IsEmpty())
+ if (arrayBufferV8Value.IsEmpty())
return false;
arrayBuffer = V8ArrayBuffer::toNative(arrayBufferV8Value.As<v8::Object>());
if (!arrayBuffer)
@@ -2368,12 +2367,23 @@
{
}
-template<typename T>
-inline void neuterBinding(T* object)
+inline void neuterBinding(ArrayBuffer* object)
{
Vector<DOMDataStore*>& allStores = V8PerIsolateData::current()->allStores();
for (size_t i = 0; i < allStores.size(); i++) {
- v8::Handle<v8::Object> wrapper = allStores[i]->get(object);
+ v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBuffer>(object);
+ if (!wrapper.IsEmpty()) {
+ ASSERT(wrapper->IsArrayBuffer());
+ v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter();
+ }
+ }
+}
+
+inline void neuterBinding(ArrayBufferView* object)
+{
+ Vector<DOMDataStore*>& allStores = V8PerIsolateData::current()->allStores();
+ for (size_t i = 0; i < allStores.size(); i++) {
+ v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBufferView>(object);
if (!wrapper.IsEmpty())
wrapper->SetIndexedPropertiesToExternalArrayData(0, v8::kExternalByteArray, 0);
}
@@ -2385,7 +2395,7 @@
for (size_t i = 0; i < arrayBuffers.size(); i++) {
if (arrayBuffers[i]->isNeutered()) {
- setDOMException(INVALID_STATE_ERR, isolate);
+ setDOMException(InvalidStateError, isolate);
didThrow = true;
return nullptr;
}
@@ -2403,7 +2413,7 @@
bool result = arrayBuffers[i]->transfer(contents->at(i), neuteredViews);
if (!result) {
- setDOMException(INVALID_STATE_ERR, isolate);
+ setDOMException(InvalidStateError, isolate);
didThrow = true;
return nullptr;
}
@@ -2438,11 +2448,11 @@
// If there was an input error, throw a new exception outside
// of the TryCatch scope.
didThrow = true;
- setDOMException(DATA_CLONE_ERR, isolate);
+ setDOMException(DataCloneError, isolate);
return;
case Serializer::InvalidStateError:
didThrow = true;
- setDOMException(INVALID_STATE_ERR, isolate);
+ setDOMException(InvalidStateError, isolate);
return;
case Serializer::JSFailure:
// If there was a JS failure (but no exception), there's not
@@ -2480,6 +2490,10 @@
COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes);
Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->bloatedCharacters()), 2 * m_data.length(), isolate);
Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get());
+
+ // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed.
+ // Holding a RefPtr ensures we are alive (along with our internal data) throughout the operation.
+ RefPtr<SerializedScriptValue> protect(this);
return deserializer.deserialize();
}
diff --git a/Source/bindings/v8/V8Binding.cpp b/Source/bindings/v8/V8Binding.cpp
index 6614112..c16f74a 100644
--- a/Source/bindings/v8/V8Binding.cpp
+++ b/Source/bindings/v8/V8Binding.cpp
@@ -54,6 +54,7 @@
#include "core/page/Settings.h"
#include "core/workers/WorkerGlobalScope.h"
#include "core/xml/XPathNSResolver.h"
+#include "wtf/ArrayBufferContents.h"
#include "wtf/MainThread.h"
#include "wtf/MathExtras.h"
#include "wtf/StdLibExtras.h"
@@ -68,7 +69,7 @@
v8::Handle<v8::Value> setDOMException(int exceptionCode, v8::Isolate* isolate)
{
- return V8ThrowException::setDOMException(exceptionCode, isolate);
+ return V8ThrowException::throwDOMException(exceptionCode, isolate);
}
v8::Handle<v8::Value> throwError(V8ErrorType errorType, const char* message, v8::Isolate* isolate)
@@ -91,6 +92,28 @@
return V8ThrowException::throwNotEnoughArgumentsError(isolate);
}
+class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
+ virtual void* Allocate(size_t size) OVERRIDE
+ {
+ void* data;
+ if (WTF::ArrayBufferContents::allocateMemory(size, WTF::ArrayBufferContents::ZeroInitialize, data))
+ return data;
+ return 0;
+ }
+
+ virtual void Free(void* data) OVERRIDE
+ {
+ WTF::ArrayBufferContents::freeMemory(data);
+ }
+};
+
+v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator()
+{
+ DEFINE_STATIC_LOCAL(ArrayBufferAllocator, arrayBufferAllocator, ());
+ return &arrayBufferAllocator;
+}
+
+
v8::Handle<v8::Value> v8Array(PassRefPtr<DOMStringList> stringList, v8::Isolate* isolate)
{
if (!stringList)
diff --git a/Source/bindings/v8/V8Binding.h b/Source/bindings/v8/V8Binding.h
index bbe571d..315ea52 100644
--- a/Source/bindings/v8/V8Binding.h
+++ b/Source/bindings/v8/V8Binding.h
@@ -70,6 +70,8 @@
// A helper for throwing JavaScript TypeError for not enough arguments.
v8::Handle<v8::Value> throwNotEnoughArgumentsError(v8::Isolate*);
+ v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator();
+
inline v8::Handle<v8::Value> argumentOrNull(const v8::FunctionCallbackInfo<v8::Value>& args, int index)
{
return index >= args.Length() ? v8::Local<v8::Value>() : args[index];
@@ -84,26 +86,26 @@
return v8::Handle<v8::Value>(isolate ? v8::Null(isolate) : v8::Null());
}
- template<typename T, typename V>
- inline void v8SetReturnValue(const T& args, V v)
+ template<typename CallbackInfo, typename V>
+ inline void v8SetReturnValue(const CallbackInfo& args, V v)
{
args.GetReturnValue().Set(v);
}
- template<typename T>
- inline void v8SetReturnValueBool(const T& args, bool v)
+ template<typename CallbackInfo>
+ inline void v8SetReturnValueBool(const CallbackInfo& args, bool v)
{
args.GetReturnValue().Set(v);
}
- template<typename T>
- inline void v8SetReturnValueInt(const T& args, int v)
+ template<typename CallbackInfo>
+ inline void v8SetReturnValueInt(const CallbackInfo& args, int v)
{
args.GetReturnValue().Set(v);
}
- template<typename T>
- inline void v8SetReturnValueUnsigned(const T& args, unsigned v)
+ template<typename CallbackInfo>
+ inline void v8SetReturnValueUnsigned(const CallbackInfo& args, unsigned v)
{
// FIXME: this is temporary workaround to a v8 bug
if (V8_LIKELY((v & (1 << 31)) == 0)) {
@@ -113,12 +115,38 @@
args.GetReturnValue().Set(v8::Integer::NewFromUnsigned(v, args.GetReturnValue().GetIsolate()));
}
- template<typename T>
- inline void v8SetReturnValueNull(const T& args)
+ template<typename CallbackInfo>
+ inline void v8SetReturnValueNull(const CallbackInfo& args)
{
args.GetReturnValue().SetNull();
}
+ enum TreatNullStringAs {
+ NullStringAsEmpty,
+ NullStringAsNull,
+ NullStringAsUndefined,
+ };
+
+ template <class CallbackInfo>
+ inline void v8SetReturnValueString(const CallbackInfo& info, const String& string, v8::Isolate* isolate, TreatNullStringAs treatNullStringAs = NullStringAsEmpty)
+ {
+ if (string.isNull()) {
+ switch (treatNullStringAs) {
+ case NullStringAsEmpty:
+ v8SetReturnValue(info, v8::String::Empty(isolate));
+ break;
+ case NullStringAsNull:
+ v8SetReturnValueNull(info);
+ break;
+ case NullStringAsUndefined:
+ v8SetReturnValue(info, v8::Undefined(isolate));
+ break;
+ }
+ return;
+ }
+ V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info, string.impl(), isolate);
+ }
+
// Convert v8 types 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.
@@ -174,27 +202,11 @@
// 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(const String& string, v8::Isolate* isolate, ReturnHandleType handleType = ReturnLocalHandle)
+ inline v8::Handle<v8::String> v8String(const String& string, v8::Isolate* isolate)
{
if (string.isNull())
return v8::String::Empty(isolate);
- return V8PerIsolateData::from(isolate)->stringCache()->v8ExternalString(string.impl(), handleType, isolate);
- }
-
- inline v8::Handle<v8::Value> v8StringOrNull(const String& string, v8::Isolate* isolate, ReturnHandleType handleType = ReturnLocalHandle)
- {
- ASSERT(isolate);
- if (string.isNull())
- return v8::Null(isolate);
- return V8PerIsolateData::from(isolate)->stringCache()->v8ExternalString(string.impl(), handleType, isolate);
- }
-
- inline v8::Handle<v8::Value> v8StringOrUndefined(const String& string, v8::Isolate* isolate, ReturnHandleType handleType = ReturnLocalHandle)
- {
- ASSERT(isolate);
- if (string.isNull())
- return v8::Undefined(isolate);
- return V8PerIsolateData::from(isolate)->stringCache()->v8ExternalString(string.impl(), handleType, isolate);
+ return V8PerIsolateData::from(isolate)->stringCache()->v8ExternalString(string.impl(), isolate);
}
inline v8::Handle<v8::Value> v8Undefined()
@@ -567,6 +579,12 @@
return *handle;
}
+ // Attaches |environment| to |function| and returns it.
+ inline v8::Local<v8::Function> createClosure(v8::FunctionCallback function, v8::Handle<v8::Value> environment)
+ {
+ return v8::FunctionTemplate::New(function, environment)->GetFunction();
+ }
+
} // namespace WebCore
#endif // V8Binding_h
diff --git a/Source/bindings/v8/V8Callback.h b/Source/bindings/v8/V8Callback.h
index 45c1660..c17cf7f 100644
--- a/Source/bindings/v8/V8Callback.h
+++ b/Source/bindings/v8/V8Callback.h
@@ -64,7 +64,7 @@
if (!value->IsFunction()) {
succeeded = false;
- setDOMException(TYPE_MISMATCH_ERR, isolate);
+ setDOMException(TypeMismatchError, isolate);
return 0;
}
diff --git a/Source/bindings/v8/V8CustomElementCallback.cpp b/Source/bindings/v8/V8CustomElementCallback.cpp
deleted file mode 100644
index 14917b1..0000000
--- a/Source/bindings/v8/V8CustomElementCallback.cpp
+++ /dev/null
@@ -1,99 +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/V8CustomElementCallback.h"
-
-#include "V8Element.h"
-#include "bindings/v8/ScriptController.h"
-#include "bindings/v8/V8Binding.h"
-#include "bindings/v8/V8HiddenPropertyName.h"
-#include "core/dom/ScriptExecutionContext.h"
-#include "wtf/PassRefPtr.h"
-
-namespace WebCore {
-
-PassRefPtr<V8CustomElementCallback> V8CustomElementCallback::create(ScriptExecutionContext* scriptExecutionContext, v8::Handle<v8::Object> owner, v8::Handle<v8::Function> ready)
-{
- if (!ready.IsEmpty())
- owner->SetHiddenValue(V8HiddenPropertyName::customElementReady(), ready);
- return adoptRef(new V8CustomElementCallback(scriptExecutionContext, ready));
-}
-
-static void weakCallback(v8::Isolate*, v8::Persistent<v8::Function>*, ScopedPersistent<v8::Function>* handle)
-{
- handle->clear();
-}
-
-V8CustomElementCallback::V8CustomElementCallback(ScriptExecutionContext* scriptExecutionContext, v8::Handle<v8::Function> ready)
- : CustomElementCallback(ready.IsEmpty() ? None : Ready)
- , ActiveDOMCallback(scriptExecutionContext)
- , m_world(DOMWrapperWorld::current())
- , m_ready(ready)
-{
- if (!m_ready.isEmpty())
- m_ready.makeWeak(&m_ready, weakCallback);
-}
-
-void V8CustomElementCallback::ready(Element* element)
-{
- if (!canInvokeCallback())
- return;
-
- v8::HandleScope handleScope;
-
- v8::Handle<v8::Context> context = toV8Context(scriptExecutionContext(), m_world.get());
- if (context.IsEmpty())
- return;
-
- v8::Context::Scope scope(context);
- v8::Isolate* isolate = context->GetIsolate();
-
- v8::Handle<v8::Function> callback = m_ready.newLocal(isolate);
- if (callback.IsEmpty())
- return;
-
- v8::Handle<v8::Value> elementHandle = toV8(element, context->Global(), isolate);
- if (elementHandle.IsEmpty()) {
- if (!isScriptControllerTerminating())
- CRASH();
- return;
- }
-
- ASSERT(elementHandle->IsObject());
- v8::Handle<v8::Object> receiver = v8::Handle<v8::Object>::Cast(elementHandle);
-
- v8::TryCatch exceptionCatcher;
- exceptionCatcher.SetVerbose(true);
- ScriptController::callFunctionWithInstrumentation(scriptExecutionContext(), callback, receiver, 0, 0);
-}
-
-} // namespace WebCore
-
diff --git a/Source/bindings/v8/V8CustomElementLifecycleCallbacks.cpp b/Source/bindings/v8/V8CustomElementLifecycleCallbacks.cpp
new file mode 100644
index 0000000..baf8d90
--- /dev/null
+++ b/Source/bindings/v8/V8CustomElementLifecycleCallbacks.cpp
@@ -0,0 +1,214 @@
+/*
+ * 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/V8CustomElementLifecycleCallbacks.h"
+
+#include "V8Element.h"
+#include "bindings/v8/DOMDataStore.h"
+#include "bindings/v8/ScriptController.h"
+#include "bindings/v8/V8Binding.h"
+#include "bindings/v8/V8HiddenPropertyName.h"
+#include "core/dom/ScriptExecutionContext.h"
+#include "wtf/PassRefPtr.h"
+
+namespace WebCore {
+
+#define CALLBACK_LIST(V) \
+ V(created, Created) \
+ V(enteredDocument, EnteredDocument) \
+ V(leftDocument, LeftDocument) \
+ V(attributeChanged, AttributeChanged)
+
+PassRefPtr<V8CustomElementLifecycleCallbacks> V8CustomElementLifecycleCallbacks::create(ScriptExecutionContext* scriptExecutionContext, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> enteredDocument, v8::Handle<v8::Function> leftDocument, v8::Handle<v8::Function> attributeChanged)
+{
+ // 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()).IsEmpty()); \
+ if (!Value.IsEmpty()) \
+ prototype->SetHiddenValue(V8HiddenPropertyName::customElement##Name(), Value);
+
+ CALLBACK_LIST(SET_HIDDEN_PROPERTY)
+#undef SET_HIDDEN_PROPERTY
+
+ return adoptRef(new V8CustomElementLifecycleCallbacks(scriptExecutionContext, prototype, created, enteredDocument, leftDocument, attributeChanged));
+}
+
+static CustomElementLifecycleCallbacks::CallbackType flagSet(v8::Handle<v8::Function> enteredDocument, v8::Handle<v8::Function> leftDocument, v8::Handle<v8::Function> attributeChanged)
+{
+ // V8 Custom Elements always run created to swizzle prototypes.
+ int flags = CustomElementLifecycleCallbacks::Created;
+
+ if (!enteredDocument.IsEmpty())
+ flags |= CustomElementLifecycleCallbacks::EnteredDocument;
+
+ if (!leftDocument.IsEmpty())
+ flags |= CustomElementLifecycleCallbacks::LeftDocument;
+
+ if (!attributeChanged.IsEmpty())
+ flags |= CustomElementLifecycleCallbacks::AttributeChanged;
+
+ return CustomElementLifecycleCallbacks::CallbackType(flags);
+}
+
+template <typename T>
+static void weakCallback(v8::Isolate*, v8::Persistent<T>*, ScopedPersistent<T>* handle)
+{
+ handle->clear();
+}
+
+V8CustomElementLifecycleCallbacks::V8CustomElementLifecycleCallbacks(ScriptExecutionContext* scriptExecutionContext, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> enteredDocument, v8::Handle<v8::Function> leftDocument, v8::Handle<v8::Function> attributeChanged)
+ : CustomElementLifecycleCallbacks(flagSet(enteredDocument, leftDocument, attributeChanged))
+ , ActiveDOMCallback(scriptExecutionContext)
+ , m_world(DOMWrapperWorld::current())
+ , m_prototype(prototype)
+ , m_created(created)
+ , m_enteredDocument(enteredDocument)
+ , m_leftDocument(leftDocument)
+ , m_attributeChanged(attributeChanged)
+{
+ m_prototype.makeWeak(&m_prototype, weakCallback<v8::Object>);
+
+#define MAKE_WEAK(Var, _) \
+ if (!m_##Var.isEmpty()) \
+ m_##Var.makeWeak(&m_##Var, weakCallback<v8::Function>);
+
+ CALLBACK_LIST(MAKE_WEAK)
+#undef MAKE_WEAK
+}
+
+void V8CustomElementLifecycleCallbacks::created(Element* element)
+{
+ if (!canInvokeCallback())
+ return;
+
+ element->setIsUpgradedCustomElement();
+
+ v8::HandleScope handleScope;
+ v8::Handle<v8::Context> context = toV8Context(scriptExecutionContext(), m_world.get());
+ if (context.IsEmpty())
+ return;
+
+ v8::Context::Scope scope(context);
+ v8::Isolate* isolate = context->GetIsolate();
+
+ v8::Handle<v8::Object> receiver = DOMDataStore::current(isolate)->get<V8Element>(element);
+ 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
+ // prototype when wrapped.
+ v8::Handle<v8::Object> prototype = m_prototype.newLocal(isolate);
+ if (prototype.IsEmpty())
+ return;
+ receiver->SetPrototype(prototype);
+ }
+
+ v8::Handle<v8::Function> callback = m_created.newLocal(isolate);
+ if (callback.IsEmpty())
+ return;
+
+ if (receiver.IsEmpty())
+ receiver = toV8(element, context->Global(), isolate).As<v8::Object>();
+
+ ASSERT(!receiver.IsEmpty());
+
+ v8::TryCatch exceptionCatcher;
+ exceptionCatcher.SetVerbose(true);
+ ScriptController::callFunctionWithInstrumentation(scriptExecutionContext(), callback, receiver, 0, 0);
+}
+
+void V8CustomElementLifecycleCallbacks::enteredDocument(Element* element)
+{
+ call(m_enteredDocument, element);
+}
+
+void V8CustomElementLifecycleCallbacks::leftDocument(Element* element)
+{
+ call(m_leftDocument, element);
+}
+
+void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue)
+{
+ if (!canInvokeCallback())
+ return;
+
+ v8::HandleScope handleScope;
+ v8::Handle<v8::Context> context = toV8Context(scriptExecutionContext(), m_world.get());
+ if (context.IsEmpty())
+ return;
+
+ v8::Context::Scope scope(context);
+ v8::Isolate* isolate = context->GetIsolate();
+
+ v8::Handle<v8::Object> receiver = toV8(element, context->Global(), isolate).As<v8::Object>();
+ ASSERT(!receiver.IsEmpty());
+
+ v8::Handle<v8::Function> callback = m_attributeChanged.newLocal(isolate);
+ if (callback.IsEmpty())
+ return;
+
+ v8::Handle<v8::Value> argv[] = {
+ v8String(name, isolate),
+ oldValue.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::Value>(v8String(oldValue, isolate)),
+ newValue.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::Value>(v8String(newValue, isolate))
+ };
+
+ v8::TryCatch exceptionCatcher;
+ exceptionCatcher.SetVerbose(true);
+ ScriptController::callFunctionWithInstrumentation(scriptExecutionContext(), callback, receiver, WTF_ARRAY_LENGTH(argv), argv);
+}
+
+void V8CustomElementLifecycleCallbacks::call(const ScopedPersistent<v8::Function>& weakCallback, Element* element)
+{
+ if (!canInvokeCallback())
+ return;
+
+ v8::HandleScope handleScope;
+ v8::Handle<v8::Context> context = toV8Context(scriptExecutionContext(), m_world.get());
+ if (context.IsEmpty())
+ return;
+
+ v8::Context::Scope scope(context);
+ v8::Isolate* isolate = context->GetIsolate();
+
+ v8::Handle<v8::Function> callback = weakCallback.newLocal(isolate);
+ if (callback.IsEmpty())
+ return;
+
+ v8::Handle<v8::Object> receiver = toV8(element, context->Global(), isolate).As<v8::Object>();
+ ASSERT(!receiver.IsEmpty());
+
+ v8::TryCatch exceptionCatcher;
+ exceptionCatcher.SetVerbose(true);
+ ScriptController::callFunctionWithInstrumentation(scriptExecutionContext(), callback, receiver, 0, 0);
+}
+
+} // namespace WebCore
diff --git a/Source/bindings/v8/V8CustomElementLifecycleCallbacks.h b/Source/bindings/v8/V8CustomElementLifecycleCallbacks.h
new file mode 100644
index 0000000..81264c5
--- /dev/null
+++ b/Source/bindings/v8/V8CustomElementLifecycleCallbacks.h
@@ -0,0 +1,71 @@
+/*
+ * 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 V8CustomElementLifecycleCallbacks_h
+#define V8CustomElementLifecycleCallbacks_h
+
+#include "bindings/v8/ActiveDOMCallback.h"
+#include "bindings/v8/DOMWrapperWorld.h"
+#include "bindings/v8/ScopedPersistent.h"
+#include "core/dom/CustomElementLifecycleCallbacks.h"
+#include <v8.h>
+
+namespace WebCore {
+
+class Element;
+class ScriptExecutionContext;
+
+class V8CustomElementLifecycleCallbacks : public CustomElementLifecycleCallbacks, ActiveDOMCallback {
+public:
+ static PassRefPtr<V8CustomElementLifecycleCallbacks> create(ScriptExecutionContext*, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> enteredDocument, v8::Handle<v8::Function> leftDocument, v8::Handle<v8::Function> attributeChanged);
+
+ virtual ~V8CustomElementLifecycleCallbacks() { }
+
+private:
+ V8CustomElementLifecycleCallbacks(ScriptExecutionContext*, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> enteredDocument, v8::Handle<v8::Function> leftDocument, v8::Handle<v8::Function> attributeChanged);
+
+ virtual void created(Element*) OVERRIDE;
+ virtual void enteredDocument(Element*) OVERRIDE;
+ virtual void leftDocument(Element*) OVERRIDE;
+ virtual void attributeChanged(Element*, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue) OVERRIDE;
+
+ void call(const ScopedPersistent<v8::Function>& weakCallback, Element*);
+
+ RefPtr<DOMWrapperWorld> m_world;
+ ScopedPersistent<v8::Object> m_prototype;
+ ScopedPersistent<v8::Function> m_created;
+ ScopedPersistent<v8::Function> m_enteredDocument;
+ ScopedPersistent<v8::Function> m_leftDocument;
+ ScopedPersistent<v8::Function> m_attributeChanged;
+};
+
+}
+
+#endif // V8CustomElementLifecycleCallbacks_h
diff --git a/Source/bindings/v8/V8DOMWrapper.h b/Source/bindings/v8/V8DOMWrapper.h
index 9e274d7..8fbfe9c 100644
--- a/Source/bindings/v8/V8DOMWrapper.h
+++ b/Source/bindings/v8/V8DOMWrapper.h
@@ -49,7 +49,7 @@
static v8::Local<v8::Object> createWrapper(v8::Handle<v8::Object> creationContext, WrapperTypeInfo*, void*, v8::Isolate*);
- template<typename T>
+ template<typename V8T, typename T>
static inline v8::Handle<v8::Object> associateObjectWithWrapper(PassRefPtr<T>, WrapperTypeInfo*, v8::Handle<v8::Object>, v8::Isolate*, WrapperConfiguration::Lifetime);
static inline void setNativeInfo(v8::Handle<v8::Object>, WrapperTypeInfo*, void*);
static inline void clearNativeInfo(v8::Handle<v8::Object>, WrapperTypeInfo*);
@@ -75,13 +75,13 @@
wrapper->SetAlignedPointerInInternalField(v8DOMWrapperObjectIndex, 0);
}
- template<typename T>
+ template<typename V8T, typename T>
inline v8::Handle<v8::Object> V8DOMWrapper::associateObjectWithWrapper(PassRefPtr<T> object, WrapperTypeInfo* type, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, WrapperConfiguration::Lifetime lifetime)
{
- setNativeInfo(wrapper, type, object.get());
+ setNativeInfo(wrapper, type, V8T::toInternalPointer(object.get()));
ASSERT(maybeDOMWrapper(wrapper));
WrapperConfiguration configuration = buildWrapperConfiguration(object.get(), lifetime);
- DOMDataStore::setWrapper(object.leakRef(), wrapper, isolate, configuration);
+ DOMDataStore::setWrapper<V8T>(object.leakRef(), wrapper, isolate, configuration);
return wrapper;
}
diff --git a/Source/bindings/v8/V8GCController.cpp b/Source/bindings/v8/V8GCController.cpp
index 1b76c77..8acb702 100644
--- a/Source/bindings/v8/V8GCController.cpp
+++ b/Source/bindings/v8/V8GCController.cpp
@@ -350,14 +350,15 @@
{
TRACE_EVENT_BEGIN0("v8", "minorGC");
if (isMainThread()) {
- TraceEvent::SamplingState0Scope("Blink\0Blink-MinorGC");
- v8::HandleScope scope;
- MinorGCWrapperVisitor visitor(isolate);
- v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
- visitor.notifyFinished();
-
- V8PerIsolateData::from(isolate)->setPreviousSamplingState(TraceEvent::SamplingState0Scope::current());
- TraceEvent::SamplingState0Scope::forceCurrent("Blink\0Blink-MinorGC");
+ {
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "MinorGC");
+ v8::HandleScope scope;
+ 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");
}
}
@@ -367,14 +368,15 @@
v8::HandleScope scope;
TRACE_EVENT_BEGIN0("v8", "majorGC");
if (isMainThread()) {
- TraceEvent::SamplingState0Scope("Blink\0Blink-MajorGC");
- MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos);
- v8::V8::VisitHandlesWithClassIds(&visitor);
- visitor.notifyFinished();
- V8PerIsolateData::from(isolate)->stringCache()->clearOnGC();
-
- V8PerIsolateData::from(isolate)->setPreviousSamplingState(TraceEvent::SamplingState0Scope::current());
- TraceEvent::SamplingState0Scope::forceCurrent("V8\0V8-MajorGC");
+ {
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "MajorGC");
+ MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos);
+ v8::V8::VisitHandlesWithClassIds(&visitor);
+ visitor.notifyFinished();
+ V8PerIsolateData::from(isolate)->stringCache()->clearOnGC();
+ }
+ V8PerIsolateData::from(isolate)->setPreviousSamplingState(TRACE_EVENT_GET_SAMPLING_STATE());
+ TRACE_EVENT_SET_SAMPLING_STATE("V8", "MajorGC");
} else {
MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos);
v8::V8::VisitHandlesWithClassIds(&visitor);
@@ -405,7 +407,7 @@
{
TRACE_EVENT_END0("v8", "minorGC");
if (isMainThread())
- TraceEvent::SamplingState0Scope::forceCurrent(V8PerIsolateData::from(isolate)->previousSamplingState());
+ TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState());
}
void V8GCController::majorGCEpilogue(v8::Isolate* isolate)
@@ -420,7 +422,7 @@
TRACE_EVENT_END0("v8", "majorGC");
if (isMainThread())
- TraceEvent::SamplingState0Scope::forceCurrent(V8PerIsolateData::from(isolate)->previousSamplingState());
+ TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState());
}
void V8GCController::checkMemoryUsage()
diff --git a/Source/bindings/v8/V8HiddenPropertyName.h b/Source/bindings/v8/V8HiddenPropertyName.h
index bce82ae..8979f5f 100644
--- a/Source/bindings/v8/V8HiddenPropertyName.h
+++ b/Source/bindings/v8/V8HiddenPropertyName.h
@@ -39,19 +39,24 @@
V(adaptorFunctionPeer) \
V(attributeListener) \
V(callback) \
- V(customElementReady) \
+ V(customElementAttributeChanged) \
+ V(customElementCreated) \
+ V(customElementDocument) \
+ V(customElementEnteredDocument) \
+ V(customElementIsInterfacePrototypeObject) \
+ V(customElementLeftDocument) \
+ V(customElementNamespaceURI) \
+ V(customElementTagName) \
+ V(customElementType) \
+ V(data) \
V(detail) \
V(document) \
V(event) \
- V(isCustomElementInterfacePrototypeObject) \
V(listener) \
- V(name) \
- V(namespaceURI) \
V(scriptState) \
V(sleepFunction) \
V(state) \
V(toStringString) \
- V(type) \
V(typedArrayHiddenCopyMethod)
class V8HiddenPropertyName {
diff --git a/Source/bindings/v8/V8Initializer.cpp b/Source/bindings/v8/V8Initializer.cpp
index 4c60665..c1ff7cb 100644
--- a/Source/bindings/v8/V8Initializer.cpp
+++ b/Source/bindings/v8/V8Initializer.cpp
@@ -36,6 +36,8 @@
#include "bindings/v8/V8PerContextData.h"
#include "core/dom/Document.h"
#include "core/inspector/ScriptCallStack.h"
+#include "core/page/ConsoleTypes.h"
+#include "core/page/ContentSecurityPolicy.h"
#include "core/page/DOMWindow.h"
#include "core/page/Frame.h"
#include "core/platform/MemoryUsageSupport.h"
@@ -103,6 +105,15 @@
targetWindow->printErrorMessage(targetWindow->crossDomainAccessErrorMessage(activeDOMWindow()));
}
+static bool codeGenerationCheckCallbackInMainThread(v8::Local<v8::Context> context)
+{
+ if (ScriptExecutionContext* scriptExecutionContext = toScriptExecutionContext(context)) {
+ if (ContentSecurityPolicy* policy = toDocument(scriptExecutionContext)->contentSecurityPolicy())
+ return policy->allowEval(ScriptState::forContext(context));
+ }
+ return false;
+}
+
static void initializeV8Common()
{
v8::V8::AddGCPrologueCallback(V8GCController::gcPrologue);
@@ -126,6 +137,7 @@
v8::V8::SetFatalErrorHandler(reportFatalErrorInMainThread);
v8::V8::AddMessageListener(messageHandlerInMainThread);
v8::V8::SetFailedAccessCheckCallbackFunction(failedAccessCheckCallbackInMainThread);
+ v8::V8::SetAllowCodeGenerationFromStringsCallback(codeGenerationCheckCallbackInMainThread);
ScriptProfiler::initialize();
V8PerIsolateData::ensureInitialized(isolate);
}
diff --git a/Source/bindings/v8/V8NPObject.cpp b/Source/bindings/v8/V8NPObject.cpp
index a08dcd0..0505e0e 100644
--- a/Source/bindings/v8/V8NPObject.cpp
+++ b/Source/bindings/v8/V8NPObject.cpp
@@ -29,13 +29,13 @@
*/
#include "config.h"
+
#include "bindings/v8/V8NPObject.h"
#include "V8HTMLAppletElement.h"
#include "V8HTMLEmbedElement.h"
#include "V8HTMLObjectElement.h"
#include "bindings/v8/NPV8Object.h"
-#include "bindings/v8/ScriptController.h"
#include "bindings/v8/UnsafePersistent.h"
#include "bindings/v8/V8Binding.h"
#include "bindings/v8/V8NPUtils.h"
@@ -43,8 +43,6 @@
#include "bindings/v8/npruntime_impl.h"
#include "bindings/v8/npruntime_priv.h"
#include "core/html/HTMLPlugInElement.h"
-#include "core/page/DOMWindow.h"
-#include "core/page/Frame.h"
#include "wtf/OwnArrayPtr.h"
namespace WebCore {
@@ -108,16 +106,12 @@
return;
}
- // Determine the object owner for the calling context.
- DOMWindow* domWindow = firstDOMWindow();
- ASSERT(domWindow);
- NPP owner = domWindow->frame() ? domWindow->frame()->script()->frameNPP() : 0;
-
// Wrap up parameters.
int numArgs = args.Length();
OwnArrayPtr<NPVariant> npArgs = adoptArrayPtr(new NPVariant[numArgs]);
+
for (int i = 0; i < numArgs; i++)
- convertV8ObjectToNPVariant(args[i], owner, &npArgs[i]);
+ convertV8ObjectToNPVariant(args[i], npObject, &npArgs[i]);
NPVariant result;
VOID_TO_NPVARIANT(result);
@@ -152,7 +146,7 @@
// Unwrap return values.
v8::Handle<v8::Value> returnValue;
if (_NPN_IsAlive(npObject))
- returnValue = convertNPVariantToV8Object(&result, args.GetIsolate());
+ returnValue = convertNPVariantToV8Object(&result, npObject, args.GetIsolate());
_NPN_ReleaseVariantValue(&result);
v8SetReturnValue(args, returnValue);
@@ -232,6 +226,7 @@
if (!npObject || !_NPN_IsAlive(npObject))
return throwError(v8ReferenceError, "NPObject deleted", isolate);
+
if (npObject->_class->hasProperty && npObject->_class->getProperty && npObject->_class->hasProperty(npObject, identifier)) {
if (!_NPN_IsAlive(npObject))
return throwError(v8ReferenceError, "NPObject deleted", isolate);
@@ -243,8 +238,7 @@
v8::Handle<v8::Value> returnValue;
if (_NPN_IsAlive(npObject))
- returnValue = convertNPVariantToV8Object(&result, isolate);
-
+ returnValue = convertNPVariantToV8Object(&result, npObject, isolate);
_NPN_ReleaseVariantValue(&result);
return returnValue;
@@ -324,14 +318,9 @@
if (!_NPN_IsAlive(npObject))
return throwError(v8ReferenceError, "NPObject deleted", isolate);
- // Determine the object owner for the calling context.
- DOMWindow* domWindow = firstDOMWindow();
- ASSERT(domWindow);
- NPP owner = domWindow->frame() ? domWindow->frame()->script()->frameNPP() : 0;
-
NPVariant npValue;
VOID_TO_NPVARIANT(npValue);
- convertV8ObjectToNPVariant(value, owner, &npValue);
+ convertV8ObjectToNPVariant(value, npObject, &npValue);
bool success = npObject->_class->setProperty(npObject, identifier, &npValue);
_NPN_ReleaseVariantValue(&npValue);
if (success)
@@ -426,7 +415,7 @@
_NPN_ReleaseObject(npObject);
}
-v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object)
+v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root)
{
static v8::Persistent<v8::FunctionTemplate> npObjectDesc;
@@ -469,6 +458,7 @@
// KJS retains the object as part of its wrapper (see Bindings::CInstance).
_NPN_RetainObject(object);
+ _NPN_RegisterObject(object, root);
WrapperConfiguration configuration = buildWrapperConfiguration(object, WrapperConfiguration::Dependent);
staticNPObjectMap().set(object, value, configuration);
diff --git a/Source/bindings/v8/V8NPObject.h b/Source/bindings/v8/V8NPObject.h
index f346268..cd8d403 100644
--- a/Source/bindings/v8/V8NPObject.h
+++ b/Source/bindings/v8/V8NPObject.h
@@ -54,7 +54,7 @@
// Get a wrapper for a NPObject.
// If the object is already wrapped, the pre-existing wrapper will be returned. If the object is not wrapped, wrap it, and
// give V8 a weak reference to the wrapper which will cleanup when there are no more JS references to the object.
-v8::Local<v8::Object> createV8ObjectForNPObject(NPObject*);
+v8::Local<v8::Object> createV8ObjectForNPObject(NPObject*, NPObject* root);
// Tell V8 to forcibly remove an object.
// This is used at plugin teardown so that the caller can aggressively unload the plugin library. After calling this
diff --git a/Source/bindings/v8/V8NPUtils.cpp b/Source/bindings/v8/V8NPUtils.cpp
index db44460..b8b13a4 100644
--- a/Source/bindings/v8/V8NPUtils.cpp
+++ b/Source/bindings/v8/V8NPUtils.cpp
@@ -42,7 +42,7 @@
namespace WebCore {
-void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPP owner, NPVariant* result)
+void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NPVariant* result)
{
VOID_TO_NPVARIANT(*result);
@@ -69,17 +69,14 @@
STRINGN_TO_NPVARIANT(utf8Chars, length-1, *result);
} else if (object->IsObject()) {
DOMWindow* window = toDOMWindow(v8::Context::GetCurrent());
- if (owner) {
- NPObject* npobject = npCreateV8ScriptObject(
- owner, v8::Handle<v8::Object>::Cast(object), window);
- OBJECT_TO_NPVARIANT(npobject, *result);
- } else {
- NULL_TO_NPVARIANT(*result);
- }
+ NPObject* npobject = npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(object), window);
+ if (npobject)
+ _NPN_RegisterObject(npobject, owner);
+ OBJECT_TO_NPVARIANT(npobject, *result);
}
}
-v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant* variant, v8::Isolate* isolate)
+v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant* variant, NPObject* owner, v8::Isolate* isolate)
{
NPVariantType type = variant->type;
@@ -102,7 +99,7 @@
NPObject* object = NPVARIANT_TO_OBJECT(*variant);
if (V8NPObject* v8Object = npObjectToV8NPObject(object))
return v8::Local<v8::Object>::New(isolate, v8Object->v8Object);
- return createV8ObjectForNPObject(object);
+ return createV8ObjectForNPObject(object, owner);
}
default:
return v8::Undefined();
diff --git a/Source/bindings/v8/V8NPUtils.h b/Source/bindings/v8/V8NPUtils.h
index 5885f57..5ed251f 100644
--- a/Source/bindings/v8/V8NPUtils.h
+++ b/Source/bindings/v8/V8NPUtils.h
@@ -36,12 +36,11 @@
namespace WebCore {
// Convert a V8 Value of any type (string, bool, object, etc) to a NPVariant.
-void convertV8ObjectToNPVariant(v8::Local<v8::Value>, NPP, NPVariant*);
+void convertV8ObjectToNPVariant(v8::Local<v8::Value>, NPObject*, NPVariant*);
-// Convert a NPVariant (string, bool, object, etc) back to a V8 Value. If the
-// NPVariant contains an NPObject then the returned v8 object will remain valid
-// until the NPObject's owning plugin or frame is destroyed.
-v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant*, v8::Isolate*);
+// Convert a NPVariant (string, bool, object, etc) back to a V8 Value. The owner object is the NPObject which relates to the
+// object, if the object is an Object. The created NPObject will be tied to the lifetime of the owner.
+v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant*, NPObject*, v8::Isolate*);
// Helper function to create an NPN String Identifier from a v8 string.
NPIdentifier getStringIdentifier(v8::Handle<v8::String>);
diff --git a/Source/bindings/v8/V8PerContextData.cpp b/Source/bindings/v8/V8PerContextData.cpp
index 95943da..509013a 100644
--- a/Source/bindings/v8/V8PerContextData.cpp
+++ b/Source/bindings/v8/V8PerContextData.cpp
@@ -53,7 +53,7 @@
disposeMapWithUnsafePersistentValues(&m_wrapperBoilerplates);
disposeMapWithUnsafePersistentValues(&m_constructorMap);
- disposeMapWithUnsafePersistentValues(&m_customElementPrototypeMap);
+ m_customElementBindings.clear();
m_context.Dispose();
}
@@ -130,6 +130,21 @@
return function;
}
+
+void V8PerContextData::addCustomElementBinding(const AtomicString& type, PassOwnPtr<CustomElementBinding> binding)
+{
+ ASSERT(!m_customElementBindings->contains(type));
+ m_customElementBindings->add(type, binding);
+}
+
+CustomElementBinding* V8PerContextData::customElementBinding(const AtomicString& type)
+{
+ CustomElementBindingMap::const_iterator it = m_customElementBindings->find(type);
+ ASSERT(it != m_customElementBindings->end());
+ return it->value.get();
+}
+
+
static v8::Handle<v8::Value> createDebugData(const char* worldName, int debugId)
{
char buffer[32];
diff --git a/Source/bindings/v8/V8PerContextData.h b/Source/bindings/v8/V8PerContextData.h
index b4fc464..af9357d 100644
--- a/Source/bindings/v8/V8PerContextData.h
+++ b/Source/bindings/v8/V8PerContextData.h
@@ -31,6 +31,7 @@
#ifndef V8PerContextData_h
#define V8PerContextData_h
+#include "bindings/v8/CustomElementBinding.h"
#include "bindings/v8/ScopedPersistent.h"
#include "bindings/v8/UnsafePersistent.h"
#include "bindings/v8/V8DOMActivityLogger.h"
@@ -107,18 +108,15 @@
m_activityLogger = logger;
}
- typedef WTF::HashMap<AtomicString, UnsafePersistent<v8::Object> > CustomElementPrototypeMap;
-
- CustomElementPrototypeMap* customElementPrototypes()
- {
- return &m_customElementPrototypeMap;
- }
+ void addCustomElementBinding(const AtomicString& type, PassOwnPtr<CustomElementBinding>);
+ CustomElementBinding* customElementBinding(const AtomicString& type);
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()))
{
}
@@ -144,7 +142,8 @@
v8::Persistent<v8::Context> m_context;
ScopedPersistent<v8::Value> m_errorPrototype;
- CustomElementPrototypeMap m_customElementPrototypeMap;
+ typedef WTF::HashMap<AtomicString, OwnPtr<CustomElementBinding> > CustomElementBindingMap;
+ OwnPtr<CustomElementBindingMap> m_customElementBindings;
};
class V8PerContextDebugData {
diff --git a/Source/bindings/v8/V8ScriptRunner.cpp b/Source/bindings/v8/V8ScriptRunner.cpp
index 3c5cadf..e93d40f 100644
--- a/Source/bindings/v8/V8ScriptRunner.cpp
+++ b/Source/bindings/v8/V8ScriptRunner.cpp
@@ -39,7 +39,7 @@
PassOwnPtr<v8::ScriptData> V8ScriptRunner::precompileScript(v8::Handle<v8::String> code, CachedScript* cachedScript)
{
TRACE_EVENT0("v8", "v8.compile");
- TraceEvent::SamplingState0Scope("V8\0V8-Compile");
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Compile");
// A pseudo-randomly chosen ID used to store and retrieve V8 ScriptData from
// the CachedScript. If the format changes, this ID should be changed too.
static const unsigned dataTypeID = 0xECC13BD7;
@@ -66,7 +66,7 @@
v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition& scriptStartPosition, v8::ScriptData* scriptData, v8::Isolate* isolate)
{
TRACE_EVENT0("v8", "v8.compile");
- TraceEvent::SamplingState0Scope("V8\0V8-Compile");
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Compile");
v8::Handle<v8::String> name = v8String(fileName, isolate);
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);
@@ -77,7 +77,7 @@
v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Handle<v8::Script> script, ScriptExecutionContext* context)
{
TRACE_EVENT0("v8", "v8.run");
- TraceEvent::SamplingState0Scope("V8\0V8-Execution");
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
if (script.IsEmpty())
return v8::Local<v8::Value>();
@@ -108,7 +108,7 @@
v8::Local<v8::Value> V8ScriptRunner::compileAndRunInternalScript(v8::Handle<v8::String> source, v8::Isolate* isolate, const String& fileName, const TextPosition& scriptStartPosition, v8::ScriptData* scriptData)
{
TRACE_EVENT0("v8", "v8.run");
- TraceEvent::SamplingState0Scope("V8\0V8-Execution");
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, fileName, scriptStartPosition, scriptData, isolate);
if (script.IsEmpty())
return v8::Local<v8::Value>();
@@ -122,7 +122,7 @@
v8::Local<v8::Value> V8ScriptRunner::callFunction(v8::Handle<v8::Function> function, ScriptExecutionContext* context, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[])
{
TRACE_EVENT0("v8", "v8.callFunction");
- TraceEvent::SamplingState0Scope("V8\0V8-Execution");
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
V8GCController::checkMemoryUsage();
if (V8RecursionScope::recursionLevel() >= kMaxRecursionDepth)
@@ -137,7 +137,7 @@
v8::Local<v8::Value> V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[], v8::Isolate* isolate)
{
TRACE_EVENT0("v8", "v8.callFunction");
- TraceEvent::SamplingState0Scope("V8\0V8-Execution");
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
V8RecursionScope::MicrotaskSuppression recursionScope;
v8::Local<v8::Value> result = function->Call(receiver, argc, args);
crashIfV8IsDead();
@@ -147,7 +147,7 @@
v8::Local<v8::Value> V8ScriptRunner::callAsFunction(v8::Handle<v8::Object> object, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[])
{
TRACE_EVENT0("v8", "v8.callFunction");
- TraceEvent::SamplingState0Scope("V8\0V8-Execution");
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
V8RecursionScope::MicrotaskSuppression recursionScope;
v8::Local<v8::Value> result = object->CallAsFunction(receiver, argc, args);
crashIfV8IsDead();
@@ -157,7 +157,7 @@
v8::Local<v8::Value> V8ScriptRunner::callAsConstructor(v8::Handle<v8::Object> object, int argc, v8::Handle<v8::Value> args[])
{
TRACE_EVENT0("v8", "v8.callFunction");
- TraceEvent::SamplingState0Scope("V8\0V8-Execution");
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
V8RecursionScope::MicrotaskSuppression recursionScope;
v8::Local<v8::Value> result = object->CallAsConstructor(argc, args);
crashIfV8IsDead();
@@ -167,7 +167,7 @@
v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Handle<v8::ObjectTemplate> objectTemplate)
{
TRACE_EVENT0("v8", "v8.newInstance");
- TraceEvent::SamplingState0Scope("V8\0V8-Execution");
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
V8RecursionScope::MicrotaskSuppression scope;
v8::Local<v8::Object> result = objectTemplate->NewInstance();
crashIfV8IsDead();
@@ -177,7 +177,7 @@
v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[])
{
TRACE_EVENT0("v8", "v8.newInstance");
- TraceEvent::SamplingState0Scope("V8\0V8-Execution");
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
V8RecursionScope::MicrotaskSuppression scope;
v8::Local<v8::Object> result = function->NewInstance(argc, argv);
crashIfV8IsDead();
@@ -187,7 +187,7 @@
v8::Local<v8::Object> V8ScriptRunner::instantiateObjectInDocument(v8::Handle<v8::Function> function, ScriptExecutionContext* context, int argc, v8::Handle<v8::Value> argv[])
{
TRACE_EVENT0("v8", "v8.newInstance");
- TraceEvent::SamplingState0Scope("V8\0V8-Execution");
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution");
V8RecursionScope scope(context);
v8::Local<v8::Object> result = function->NewInstance(argc, argv);
crashIfV8IsDead();
diff --git a/Source/bindings/v8/V8ThrowException.cpp b/Source/bindings/v8/V8ThrowException.cpp
index e6a532c..914fd5d 100644
--- a/Source/bindings/v8/V8ThrowException.cpp
+++ b/Source/bindings/v8/V8ThrowException.cpp
@@ -44,16 +44,16 @@
info.Data()->ToObject()->Set(v8::String::NewSymbol("stack"), value);
}
-v8::Handle<v8::Value> V8ThrowException::setDOMException(int ec, v8::Isolate* isolate)
+v8::Handle<v8::Value> V8ThrowException::createDOMException(int ec, const char* message, v8::Isolate* isolate)
{
if (ec <= 0 || v8::V8::IsExecutionTerminating())
return v8Undefined();
// FIXME: Handle other WebIDL exception types.
if (ec == TypeError)
- return V8ThrowException::throwTypeError(0, isolate);
+ return V8ThrowException::createTypeError(message, isolate);
- RefPtr<DOMException> domException = DOMException::create(ec);
+ RefPtr<DOMException> domException = DOMException::create(ec, message);
v8::Handle<v8::Value> exception = toV8(domException, v8::Handle<v8::Object>(), isolate);
if (exception.IsEmpty())
@@ -65,36 +65,60 @@
ASSERT(exception->IsObject());
exception->ToObject()->SetAccessor(v8::String::NewSymbol("stack"), domExceptionStackGetter, domExceptionStackSetter, error);
- return v8::ThrowException(exception);
+ return exception;
}
-v8::Handle<v8::Value> V8ThrowException::throwError(V8ErrorType type, const char* message, v8::Isolate* isolate)
+v8::Handle<v8::Value> V8ThrowException::throwDOMException(int ec, const char* message, v8::Isolate* isolate)
+{
+ v8::Handle<v8::Value> exception = createDOMException(ec, message, isolate);
+ if (exception.IsEmpty())
+ return v8Undefined();
+
+ return V8ThrowException::throwError(exception);
+}
+
+v8::Handle<v8::Value> V8ThrowException::createError(V8ErrorType type, const char* message, v8::Isolate* isolate)
{
switch (type) {
case v8RangeError:
- return v8::ThrowException(v8::Exception::RangeError(v8String(message, isolate)));
+ return v8::Exception::RangeError(v8String(message, isolate));
case v8ReferenceError:
- return v8::ThrowException(v8::Exception::ReferenceError(v8String(message, isolate)));
+ return v8::Exception::ReferenceError(v8String(message, isolate));
case v8SyntaxError:
- return v8::ThrowException(v8::Exception::SyntaxError(v8String(message, isolate)));
+ return v8::Exception::SyntaxError(v8String(message, isolate));
case v8TypeError:
- return v8::ThrowException(v8::Exception::TypeError(v8String(message, isolate)));
+ return v8::Exception::TypeError(v8String(message, isolate));
case v8GeneralError:
- return v8::ThrowException(v8::Exception::Error(v8String(message, isolate)));
+ return v8::Exception::Error(v8String(message, isolate));
default:
ASSERT_NOT_REACHED();
return v8Undefined();
}
}
+v8::Handle<v8::Value> V8ThrowException::throwError(V8ErrorType type, const char* message, v8::Isolate* isolate)
+{
+ v8::Handle<v8::Value> exception = V8ThrowException::createError(type, message, isolate);
+ if (exception.IsEmpty())
+ return v8Undefined();
+ return V8ThrowException::throwError(exception);
+}
+
+v8::Handle<v8::Value> V8ThrowException::createTypeError(const char* message, v8::Isolate* isolate)
+{
+ return v8::Exception::TypeError(v8String(message ? message : "Type error", isolate));
+}
+
v8::Handle<v8::Value> V8ThrowException::throwTypeError(const char* message, v8::Isolate* isolate)
{
- return V8ThrowException::throwError(v8TypeError, (message ? message : "Type error"), isolate);
+ v8::Handle<v8::Value> exception = V8ThrowException::createTypeError(message, isolate);
+ return V8ThrowException::throwError(exception);
}
v8::Handle<v8::Value> V8ThrowException::throwNotEnoughArgumentsError(v8::Isolate* isolate)
{
- return V8ThrowException::throwError(v8TypeError, "Not enough arguments", isolate);
+ v8::Handle<v8::Value> exception = V8ThrowException::createTypeError("Not enough arguments", isolate);
+ return V8ThrowException::throwError(exception);
}
v8::Handle<v8::Value> V8ThrowException::throwError(v8::Handle<v8::Value> exception, v8::Isolate* isolate)
diff --git a/Source/bindings/v8/V8ThrowException.h b/Source/bindings/v8/V8ThrowException.h
index bfb3315..891431d 100644
--- a/Source/bindings/v8/V8ThrowException.h
+++ b/Source/bindings/v8/V8ThrowException.h
@@ -39,12 +39,26 @@
class V8ThrowException {
public:
- static v8::Handle<v8::Value> setDOMException(int, v8::Isolate*);
+ static v8::Handle<v8::Value> createDOMException(int ec, v8::Isolate* isolate)
+ {
+ return createDOMException(ec, 0, isolate);
+ }
+ static v8::Handle<v8::Value> createDOMException(int, const char*, v8::Isolate*);
+
+ static v8::Handle<v8::Value> throwDOMException(int ec, v8::Isolate* isolate)
+ {
+ return throwDOMException(ec, 0, isolate);
+ }
+ static v8::Handle<v8::Value> throwDOMException(int, const char*, v8::Isolate*);
+
+ static v8::Handle<v8::Value> createError(V8ErrorType, const char*, v8::Isolate* = 0);
static v8::Handle<v8::Value> throwError(V8ErrorType, const char*, v8::Isolate* = 0);
static v8::Handle<v8::Value> throwError(v8::Handle<v8::Value>, v8::Isolate* = 0);
+ static v8::Handle<v8::Value> createTypeError(const char* = 0, v8::Isolate* = 0);
static v8::Handle<v8::Value> throwTypeError(const char* = 0, v8::Isolate* = 0);
+
static v8::Handle<v8::Value> throwNotEnoughArgumentsError(v8::Isolate*);
};
diff --git a/Source/bindings/v8/V8Utilities.cpp b/Source/bindings/v8/V8Utilities.cpp
index 0824efc..b470a43 100644
--- a/Source/bindings/v8/V8Utilities.cpp
+++ b/Source/bindings/v8/V8Utilities.cpp
@@ -31,11 +31,11 @@
#include "config.h"
#include "bindings/v8/V8Utilities.h"
-#include "V8ArrayBuffer.h"
#include "V8MessagePort.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/MessagePort.h"
@@ -85,7 +85,7 @@
v8::Local<v8::Value> transferrable = transferrables->Get(i);
// Validation of non-null objects, per HTML5 spec 10.3.3.
if (isUndefinedOrNull(transferrable)) {
- setDOMException(INVALID_STATE_ERR, isolate);
+ setDOMException(InvalidStateError, isolate);
return false;
}
// Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
@@ -93,7 +93,7 @@
RefPtr<MessagePort> port = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable));
// Check for duplicate MessagePorts.
if (ports.contains(port)) {
- setDOMException(INVALID_STATE_ERR, isolate);
+ setDOMException(InvalidStateError, isolate);
return false;
}
ports.append(port.release());
diff --git a/Source/bindings/v8/V8ValueCache.cpp b/Source/bindings/v8/V8ValueCache.cpp
index aabeaaa..a426764 100644
--- a/Source/bindings/v8/V8ValueCache.cpp
+++ b/Source/bindings/v8/V8ValueCache.cpp
@@ -43,7 +43,7 @@
namespace WebCore {
-static v8::Local<v8::String> makeExternalString(const String& string)
+v8::Local<v8::String> StringCache::makeExternalString(const String& string)
{
if (string.is8Bit()) {
WebCoreStringResource8* stringResource = new WebCoreStringResource8(string);
@@ -60,7 +60,7 @@
return newString;
}
-static void makeWeakCallback(v8::Isolate* isolate, v8::Persistent<v8::String>* wrapper, StringImpl* stringImpl)
+void StringCache::makeWeakCallback(v8::Isolate* isolate, v8::Persistent<v8::String>* wrapper, StringImpl* stringImpl)
{
V8PerIsolateData::current()->stringCache()->remove(stringImpl);
wrapper->Dispose(isolate);
@@ -76,7 +76,7 @@
clearOnGC();
}
-v8::Handle<v8::String> StringCache::v8ExternalStringSlow(StringImpl* stringImpl, ReturnHandleType handleType, v8::Isolate* isolate)
+v8::Handle<v8::String> StringCache::v8ExternalStringSlow(StringImpl* stringImpl, v8::Isolate* isolate)
{
if (!stringImpl->length())
return v8::String::Empty(isolate);
@@ -85,14 +85,18 @@
if (cachedV8String.isWeak()) {
m_lastStringImpl = stringImpl;
m_lastV8String = cachedV8String;
- if (handleType == ReturnUnsafeHandle)
- return cachedV8String.handle();
return cachedV8String.newLocal(isolate);
}
+ return createStringAndInsertIntoCache(stringImpl, isolate);
+}
+
+v8::Local<v8::String> StringCache::createStringAndInsertIntoCache(StringImpl* stringImpl, v8::Isolate* isolate)
+{
v8::Local<v8::String> newString = makeExternalString(String(stringImpl));
- if (newString.IsEmpty())
+ if (newString.IsEmpty()) {
return newString;
+ }
v8::Persistent<v8::String> wrapper(isolate, newString);
@@ -103,7 +107,6 @@
m_stringCache.set(stringImpl, m_lastV8String);
m_lastStringImpl = stringImpl;
-
return newString;
}
diff --git a/Source/bindings/v8/V8ValueCache.h b/Source/bindings/v8/V8ValueCache.h
index c6cabf9..881254a 100644
--- a/Source/bindings/v8/V8ValueCache.h
+++ b/Source/bindings/v8/V8ValueCache.h
@@ -36,28 +36,24 @@
namespace WebCore {
-// ReturnUnsafeHandle can be used only when it is guaranteed
-// that no V8 object allocation is conducted before the handle
-// is returned to V8. For safety, ReturnUnsafeHandle should be
-// used by auto-generated code.
-enum ReturnHandleType {
- ReturnLocalHandle,
- ReturnUnsafeHandle
-};
-
class StringCache {
public:
StringCache() { }
- v8::Handle<v8::String> v8ExternalString(StringImpl* stringImpl, ReturnHandleType handleType, v8::Isolate* isolate)
+ v8::Handle<v8::String> v8ExternalString(StringImpl* stringImpl, v8::Isolate* isolate)
{
- if (m_lastStringImpl.get() == stringImpl && m_lastV8String.isWeak()) {
- if (handleType == ReturnUnsafeHandle)
- return m_lastV8String.handle();
+ if (m_lastStringImpl.get() == stringImpl && m_lastV8String.isWeak())
return m_lastV8String.newLocal(isolate);
- }
+ return v8ExternalStringSlow(stringImpl, isolate);
+ }
- return v8ExternalStringSlow(stringImpl, handleType, isolate);
+ template <class T>
+ void setReturnValueFromString(const T& info, StringImpl* stringImpl, v8::Isolate* isolate)
+ {
+ if (m_lastStringImpl.get() == stringImpl && m_lastV8String.isWeak())
+ info.GetReturnValue().Set(*m_lastV8String.persistent());
+ else
+ setReturnValueFromStringSlow(info, stringImpl, isolate);
}
void clearOnGC()
@@ -70,7 +66,35 @@
void reportMemoryUsage(MemoryObjectInfo*) const;
private:
- v8::Handle<v8::String> v8ExternalStringSlow(StringImpl*, ReturnHandleType, v8::Isolate*);
+ static v8::Local<v8::String> makeExternalString(const String&);
+ static void makeWeakCallback(v8::Isolate*, v8::Persistent<v8::String>*, StringImpl*);
+
+ v8::Handle<v8::String> v8ExternalStringSlow(StringImpl*, v8::Isolate*);
+
+ template <class CallbackInfo>
+ void setReturnValueFromStringSlow(const CallbackInfo& info, StringImpl* stringImpl, v8::Isolate* isolate)
+ {
+ if (!stringImpl->length()) {
+ info.GetReturnValue().SetEmptyString();
+ return;
+ }
+
+ UnsafePersistent<v8::String> cachedV8String = m_stringCache.get(stringImpl);
+ if (cachedV8String.isWeak()) {
+ m_lastStringImpl = stringImpl;
+ m_lastV8String = cachedV8String;
+ info.GetReturnValue().Set(*cachedV8String.persistent());
+ return;
+ }
+
+ v8::Local<v8::String> newString = createStringAndInsertIntoCache(stringImpl, isolate);
+ if (newString.IsEmpty())
+ info.GetReturnValue().SetEmptyString();
+ else
+ info.GetReturnValue().Set(newString);
+ }
+
+ v8::Local<v8::String> createStringAndInsertIntoCache(StringImpl*, v8::Isolate*);
HashMap<StringImpl*, UnsafePersistent<v8::String> > m_stringCache;
UnsafePersistent<v8::String> m_lastV8String;
diff --git a/Source/bindings/v8/V8WindowShell.cpp b/Source/bindings/v8/V8WindowShell.cpp
index f46e3df..f327311 100644
--- a/Source/bindings/v8/V8WindowShell.cpp
+++ b/Source/bindings/v8/V8WindowShell.cpp
@@ -271,9 +271,8 @@
// Used to avoid sleep calls in unload handlers.
ScriptController::registerExtensionIfNeeded(DateExtension::get());
- // Enables experimental i18n API in V8.
- if (RuntimeEnabledFeatures::javaScriptI18NAPIEnabled())
- ScriptController::registerExtensionIfNeeded(v8_i18n::Extension::get());
+ // Enable i18n API in V8.
+ ScriptController::registerExtensionIfNeeded(v8_i18n::Extension::get());
// Dynamically tell v8 about our extensions now.
const V8Extensions& extensions = ScriptController::registeredExtensions();
@@ -329,7 +328,7 @@
v8::Handle<v8::Object> innerGlobalObject = toInnerGlobalObject(m_context.newLocal(m_isolate));
V8DOMWrapper::setNativeInfo(innerGlobalObject, &V8Window::info, window);
innerGlobalObject->SetPrototype(windowWrapper);
- V8DOMWrapper::associateObjectWithWrapper(PassRefPtr<DOMWindow>(window), &V8Window::info, windowWrapper, m_isolate, WrapperConfiguration::Dependent);
+ V8DOMWrapper::associateObjectWithWrapper<V8Window>(PassRefPtr<DOMWindow>(window), &V8Window::info, windowWrapper, m_isolate, WrapperConfiguration::Dependent);
DOMWrapperWorld::setInitializingWindow(false);
return true;
}
@@ -440,7 +439,7 @@
if (items->hasExactlyOneItem()) {
Node* node = items->item(0);
Frame* frame = 0;
- if (node->hasTagName(HTMLNames::iframeTag) && (frame = static_cast<HTMLIFrameElement*>(node)->contentFrame()))
+ if (node->hasTagName(HTMLNames::iframeTag) && (frame = toHTMLIFrameElement(node)->contentFrame()))
return toV8(frame->document()->domWindow(), creationContext, isolate);
return toV8(node, creationContext, isolate);
}
diff --git a/Source/bindings/v8/WorkerScriptController.cpp b/Source/bindings/v8/WorkerScriptController.cpp
index 05ea847..b48d044 100644
--- a/Source/bindings/v8/WorkerScriptController.cpp
+++ b/Source/bindings/v8/WorkerScriptController.cpp
@@ -124,7 +124,7 @@
return false;
}
- V8DOMWrapper::associateObjectWithWrapper(PassRefPtr<WorkerGlobalScope>(m_workerGlobalScope), contextType, jsWorkerGlobalScope, m_isolate, WrapperConfiguration::Dependent);
+ V8DOMWrapper::associateObjectWithWrapper<V8WorkerGlobalScope>(PassRefPtr<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_context.newLocal(m_isolate)->Global()->GetPrototype());
diff --git a/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp b/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp
index cd976a0..e5f9707 100644
--- a/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp
+++ b/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp
@@ -31,55 +31,77 @@
#include "config.h"
#include "bindings/v8/custom/V8ArrayBufferCustom.h"
-#include "wtf/ArrayBuffer.h"
-#include "wtf/StdLibExtras.h"
-
-#include "V8ArrayBuffer.h"
#include "bindings/v8/V8Binding.h"
#include "core/dom/ExceptionCode.h"
+#include "wtf/ArrayBuffer.h"
+#include "wtf/StdLibExtras.h"
+
namespace WebCore {
+using namespace WTF;
+
V8ArrayBufferDeallocationObserver* V8ArrayBufferDeallocationObserver::instance()
{
DEFINE_STATIC_LOCAL(V8ArrayBufferDeallocationObserver, deallocationObserver, ());
return &deallocationObserver;
}
+WrapperTypeInfo V8ArrayBuffer::info = {
+ 0, V8ArrayBuffer::derefObject,
+ 0, 0, 0, 0, 0, WrapperTypeObjectPrototype
+};
-void V8ArrayBuffer::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
+bool V8ArrayBuffer::HasInstance(v8::Handle<v8::Value> value, v8::Isolate*, WrapperWorldType)
{
- // If we return a previously constructed ArrayBuffer,
- // e.g. from the call to ArrayBufferView.buffer, this code is called
- // with a zero-length argument list. The V8DOMWrapper will then
- // set the internal pointer in the newly-created object.
- // Unfortunately it doesn't look like it's possible to distinguish
- // between this case and that where the user calls "new
- // ArrayBuffer()" from JavaScript. To guard against problems,
- // we always create at least a zero-length ArrayBuffer, even
- // if it is immediately overwritten by the V8DOMWrapper.
-
- // Supported constructors:
- // ArrayBuffer(n) where n is an integer:
- // -- create an empty buffer of n bytes
-
- int argLength = args.Length();
- int length = 0;
- if (argLength > 0)
- length = toInt32(args[0]); // NaN/+inf/-inf returns 0, this is intended by WebIDL
- RefPtr<ArrayBuffer> buffer;
- if (length >= 0)
- buffer = ArrayBuffer::create(static_cast<unsigned>(length), 1);
- if (!buffer.get()) {
- throwError(v8RangeError, "ArrayBuffer size is not a small enough positive integer.", args.GetIsolate());
- return;
- }
- buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instance());
- v8::V8::AdjustAmountOfExternalAllocatedMemory(buffer->byteLength());
- // Transform the holder into a wrapper object for the array.
- v8::Handle<v8::Object> wrapper = args.Holder();
- V8DOMWrapper::associateObjectWithWrapper(buffer.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
- args.GetReturnValue().Set(wrapper);
+ return value->IsArrayBuffer();
}
+bool V8ArrayBuffer::HasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isolate*)
+{
+ return value->IsArrayBuffer();
+}
+
+void V8ArrayBuffer::derefObject(void* object)
+{
+ static_cast<ArrayBuffer*>(object)->deref();
+}
+
+
+v8::Handle<v8::Object> V8ArrayBuffer::createWrapper(PassRefPtr<ArrayBuffer> impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
+{
+ ASSERT(impl.get());
+ ASSERT(DOMDataStore::getWrapper<V8ArrayBuffer>(impl.get(), isolate).IsEmpty());
+
+ v8::Handle<v8::Object> wrapper = v8::ArrayBuffer::New(impl->data(), impl->byteLength());
+ v8::V8::AdjustAmountOfExternalAllocatedMemory(impl->byteLength());
+ impl->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instance());
+
+ V8DOMWrapper::associateObjectWithWrapper<V8ArrayBuffer>(impl, &info, wrapper, isolate, WrapperConfiguration::Independent);
+ return wrapper;
+}
+
+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());
+
+ v8::ArrayBuffer::Contents v8Contents = v8buffer->Externalize();
+ ArrayBufferContents contents(v8Contents.Data(), v8Contents.ByteLength());
+ RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(contents);
+ // V8 accounts for external memory even after externalizing the buffer.
+ buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instance());
+ V8DOMWrapper::associateObjectWithWrapper<V8ArrayBuffer>(buffer.release(), &info, object, v8::Isolate::GetCurrent(), WrapperConfiguration::Dependent);
+
+ arraybufferPtr = object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex);
+ ASSERT(arraybufferPtr);
+ return reinterpret_cast<ArrayBuffer*>(arraybufferPtr);
+}
+
+
} // namespace WebCore
diff --git a/Source/bindings/v8/custom/V8ArrayBufferCustom.h b/Source/bindings/v8/custom/V8ArrayBufferCustom.h
index 27059a7..f40c955 100644
--- a/Source/bindings/v8/custom/V8ArrayBufferCustom.h
+++ b/Source/bindings/v8/custom/V8ArrayBufferCustom.h
@@ -26,9 +26,14 @@
#ifndef V8ArrayBufferCustom_h
#define V8ArrayBufferCustom_h
-#include <v8.h>
+#include "bindings/v8/V8Binding.h"
+#include "bindings/v8/V8DOMWrapper.h"
+#include "bindings/v8/WrapperTypeInfo.h"
+
#include "wtf/ArrayBuffer.h"
+#include <v8.h>
+
namespace WebCore {
class V8ArrayBufferDeallocationObserver: public WTF::ArrayBufferDeallocationObserver {
@@ -40,6 +45,108 @@
static V8ArrayBufferDeallocationObserver* instance();
};
+class V8ArrayBuffer {
+public:
+ static bool HasInstance(v8::Handle<v8::Value>, v8::Isolate*, WrapperWorldType);
+ static bool HasInstanceInAnyWorld(v8::Handle<v8::Value>, v8::Isolate*);
+ static ArrayBuffer* toNative(v8::Handle<v8::Object>);
+ static void derefObject(void*);
+ static WrapperTypeInfo info;
+ static const int internalFieldCount = v8DefaultWrapperInternalFieldCount;
+ static void installPerContextProperties(v8::Handle<v8::Object>, ArrayBuffer*, v8::Isolate*) { }
+ static void installPerContextPrototypeProperties(v8::Handle<v8::Object>, v8::Isolate*) { }
+
+ static inline void* toInternalPointer(ArrayBuffer* impl)
+ {
+ return impl;
+ }
+
+ static inline ArrayBuffer* fromInternalPointer(void* impl)
+ {
+ return static_cast<ArrayBuffer*>(impl);
+ }
+
+private:
+ friend v8::Handle<v8::Object> wrap(ArrayBuffer*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
+ static v8::Handle<v8::Object> createWrapper(PassRefPtr<ArrayBuffer>, v8::Handle<v8::Object> creationContext, v8::Isolate*);
+};
+
+template<>
+class WrapperTypeTraits<ArrayBuffer > {
+public:
+ static WrapperTypeInfo* info() { return &V8ArrayBuffer::info; }
+};
+
+
+inline v8::Handle<v8::Object> wrap(ArrayBuffer* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
+{
+ ASSERT(impl);
+ ASSERT(DOMDataStore::getWrapper<V8ArrayBuffer>(impl, isolate).IsEmpty());
+ return V8ArrayBuffer::createWrapper(impl, creationContext, isolate);
}
+inline v8::Handle<v8::Value> toV8(ArrayBuffer* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
+{
+ if (UNLIKELY(!impl))
+ return v8NullWithCheck(isolate);
+ v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapper<V8ArrayBuffer>(impl, isolate);
+ if (!wrapper.IsEmpty())
+ return wrapper;
+ return wrap(impl, creationContext, isolate);
+}
+
+inline v8::Handle<v8::Value> toV8ForMainWorld(ArrayBuffer* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
+{
+ ASSERT(worldType(isolate) == MainWorld);
+ if (UNLIKELY(!impl))
+ return v8NullWithCheck(isolate);
+ v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapperForMainWorld<V8ArrayBuffer>(impl);
+ if (!wrapper.IsEmpty())
+ return wrapper;
+ return wrap(impl, creationContext, isolate);
+}
+
+template<class CallbackInfo, class Wrappable>
+inline v8::Handle<v8::Value> toV8Fast(ArrayBuffer* impl, const CallbackInfo& callbackInfo, Wrappable* wrappable)
+{
+ if (UNLIKELY(!impl))
+ return v8::Null(callbackInfo.GetIsolate());
+ v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapperFast<V8ArrayBuffer>(impl, callbackInfo, wrappable);
+ if (!wrapper.IsEmpty())
+ return wrapper;
+ return wrap(impl, callbackInfo.Holder(), callbackInfo.GetIsolate());
+}
+
+template<class CallbackInfo, class Wrappable>
+inline v8::Handle<v8::Value> toV8FastForMainWorld(ArrayBuffer* impl, const CallbackInfo& callbackInfo, Wrappable* wrappable)
+{
+ ASSERT(worldType(callbackInfo.GetIsolate()) == MainWorld);
+ if (UNLIKELY(!impl))
+ return v8Null(callbackInfo.GetIsolate());
+ v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapperForMainWorld<V8ArrayBuffer>(impl);
+ if (!wrapper.IsEmpty())
+ return wrapper;
+ return wrap(impl, callbackInfo.Holder(), callbackInfo.GetIsolate());
+}
+
+template<class CallbackInfo, class Wrappable>
+inline v8::Handle<v8::Value> toV8FastForMainWorld(PassRefPtr< ArrayBuffer > impl, const CallbackInfo& callbackInfo, Wrappable* wrappable)
+{
+ return toV8FastForMainWorld(impl.get(), callbackInfo, wrappable);
+}
+
+
+template<class CallbackInfo, class Wrappable>
+inline v8::Handle<v8::Value> toV8Fast(PassRefPtr< ArrayBuffer > impl, const CallbackInfo& callbackInfo, Wrappable* wrappable)
+{
+ return toV8Fast(impl.get(), callbackInfo, wrappable);
+}
+
+inline v8::Handle<v8::Value> toV8(PassRefPtr< ArrayBuffer > impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
+{
+ return toV8(impl.get(), creationContext, isolate);
+}
+
+} // namespace WebCore
+
#endif // V8ArrayBufferCustom_h
diff --git a/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h b/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h
index 1279c65..8d13795 100644
--- a/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h
+++ b/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h
@@ -31,13 +31,12 @@
#ifndef V8ArrayBufferViewCustom_h
#define V8ArrayBufferViewCustom_h
-#include "core/dom/ExceptionCode.h"
-#include "wtf/ArrayBuffer.h"
-
-#include "V8ArrayBuffer.h"
#include "bindings/v8/V8Binding.h"
#include "bindings/v8/V8ObjectConstructor.h"
#include "bindings/v8/custom/V8ArrayBufferCustom.h"
+#include "core/dom/ExceptionCode.h"
+
+#include "wtf/ArrayBuffer.h"
namespace WebCore {
@@ -48,7 +47,7 @@
// Returns true if it succeeded, otherwise returns false.
bool copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcArray, uint32_t length, uint32_t offset, v8::Isolate*);
-template<class ArrayClass>
+template<class JavaScriptWrapperArrayType, class ArrayClass>
void wrapArrayBufferView(const v8::FunctionCallbackInfo<v8::Value>& args, WrapperTypeInfo* type, ArrayClass array, v8::ExternalArrayType arrayType, bool hasIndexer)
{
// Transform the holder into a wrapper object for the array.
@@ -56,12 +55,12 @@
if (hasIndexer)
args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddress(), arrayType, array.get()->length());
v8::Handle<v8::Object> wrapper = args.Holder();
- V8DOMWrapper::associateObjectWithWrapper(array.release(), type, wrapper, args.GetIsolate(), WrapperConfiguration::Independent);
+ V8DOMWrapper::associateObjectWithWrapper<JavaScriptWrapperArrayType>(array.release(), type, wrapper, args.GetIsolate(), WrapperConfiguration::Independent);
args.GetReturnValue().Set(wrapper);
}
// Template function used by the ArrayBufferView*Constructor callbacks.
-template<class ArrayClass, class ElementType>
+template<class ArrayClass, class ElementType, class JavaScriptWrapperArrayType>
void constructWebGLArrayWithArrayBufferArgument(const v8::FunctionCallbackInfo<v8::Value>& args, WrapperTypeInfo* type, v8::ExternalArrayType arrayType, bool hasIndexer)
{
ArrayBuffer* buf = V8ArrayBuffer::toNative(args[0]->ToObject());
@@ -105,7 +104,7 @@
return;
}
- wrapArrayBufferView(args, type, array, arrayType, hasIndexer);
+ wrapArrayBufferView<JavaScriptWrapperArrayType>(args, type, array, arrayType, hasIndexer);
}
// Template function used by the ArrayBufferView*Constructor callbacks.
@@ -136,7 +135,7 @@
// Do not call SetIndexedPropertiesToExternalArrayData on this
// object. Not only is there no point from a performance
// perspective, but doing so causes errors in the subset() case.
- wrapArrayBufferView(args, type, array, arrayType, false);
+ wrapArrayBufferView<JavaScriptWrapperArrayType>(args, type, array, arrayType, false);
return;
}
@@ -158,7 +157,7 @@
// See whether the first argument is a ArrayBuffer.
if (V8ArrayBuffer::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate()))) {
- constructWebGLArrayWithArrayBufferArgument<ArrayClass, ElementType>(args, type, arrayType, true);
+ constructWebGLArrayWithArrayBufferArgument<ArrayClass, ElementType, JavaScriptWrapperArrayType>(args, type, arrayType, true);
return;
}
@@ -184,7 +183,7 @@
memcpy(array->baseAddress(), source->baseAddress(), length * sizeof(ElementType));
- wrapArrayBufferView(args, type, array, arrayType, true);
+ wrapArrayBufferView<JavaScriptWrapperArrayType>(args, type, array, arrayType, true);
return;
}
@@ -256,7 +255,7 @@
}
v8::Handle<v8::Object> wrapper = args.Holder();
- V8DOMWrapper::associateObjectWithWrapper(array.release(), type, wrapper, args.GetIsolate(), WrapperConfiguration::Independent);
+ V8DOMWrapper::associateObjectWithWrapper<JavaScriptWrapperArrayType>(array.release(), type, wrapper, args.GetIsolate(), WrapperConfiguration::Independent);
args.GetReturnValue().Set(wrapper);
}
diff --git a/Source/bindings/v8/custom/V8AudioContextCustom.cpp b/Source/bindings/v8/custom/V8AudioContextCustom.cpp
index 4a77ad9..b9c84ff 100644
--- a/Source/bindings/v8/custom/V8AudioContextCustom.cpp
+++ b/Source/bindings/v8/custom/V8AudioContextCustom.cpp
@@ -28,10 +28,10 @@
#include "V8AudioContext.h"
-#include "V8ArrayBuffer.h"
#include "V8AudioBuffer.h"
#include "V8OfflineAudioContext.h"
#include "bindings/v8/V8Binding.h"
+#include "bindings/v8/custom/V8ArrayBufferCustom.h"
#include "core/dom/Document.h"
#include "core/page/Frame.h"
#include "modules/webaudio/AudioBuffer.h"
@@ -71,7 +71,7 @@
// Transform the holder into a wrapper object for the audio context.
v8::Handle<v8::Object> wrapper = args.Holder();
- V8DOMWrapper::associateObjectWithWrapper(audioContext.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
+ V8DOMWrapper::associateObjectWithWrapper<V8AudioContext>(audioContext.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
args.GetReturnValue().Set(wrapper);
}
diff --git a/Source/bindings/v8/custom/V8BlobCustom.cpp b/Source/bindings/v8/custom/V8BlobCustom.cpp
index a72173c..b13f701 100644
--- a/Source/bindings/v8/custom/V8BlobCustom.cpp
+++ b/Source/bindings/v8/custom/V8BlobCustom.cpp
@@ -31,13 +31,13 @@
#include "config.h"
#include "core/fileapi/Blob.h"
-#include "V8ArrayBuffer.h"
#include "V8ArrayBufferView.h"
#include "V8Blob.h"
#include "V8File.h"
#include "bindings/v8/Dictionary.h"
#include "bindings/v8/V8Binding.h"
#include "bindings/v8/V8Utilities.h"
+#include "bindings/v8/custom/V8ArrayBufferCustom.h"
#include "core/fileapi/BlobBuilder.h"
#include "wtf/RefPtr.h"
diff --git a/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp b/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp
index b06a503..7064975 100644
--- a/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp
+++ b/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp
@@ -212,7 +212,7 @@
cssValue.get())->getFloatValue(CSSPrimitiveValue::CSS_PX));
return;
}
- v8SetReturnValue(info, v8StringOrNull(cssValue->cssText(), info.GetIsolate()));
+ v8SetReturnValueString(info, cssValue->cssText(), info.GetIsolate(), NullStringAsNull);
return;
}
@@ -220,7 +220,7 @@
if (result.isNull())
result = ""; // convert null to empty string.
- v8SetReturnValue(info, v8String(result, info.GetIsolate()));
+ v8SetReturnValueString(info, result, info.GetIsolate());
}
void V8CSSStyleDeclaration::namedPropertySetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
diff --git a/Source/bindings/v8/custom/V8CustomEventCustom.cpp b/Source/bindings/v8/custom/V8CustomEventCustom.cpp
index ff0f9b3..d03eb67 100644
--- a/Source/bindings/v8/custom/V8CustomEventCustom.cpp
+++ b/Source/bindings/v8/custom/V8CustomEventCustom.cpp
@@ -45,20 +45,46 @@
namespace WebCore {
+static v8::Handle<v8::Value> cacheState(v8::Handle<v8::Object> customEvent, v8::Handle<v8::Value> detail)
+{
+ customEvent->SetHiddenValue(V8HiddenPropertyName::detail(), detail);
+ return detail;
+}
+
+
void V8CustomEvent::detailAttrGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
{
- CustomEvent* imp = V8CustomEvent::toNative(info.Holder());
- RefPtr<SerializedScriptValue> serialized = imp->serializedScriptValue();
- if (serialized) {
- v8::Handle<v8::Value> value = info.Holder()->GetHiddenValue(V8HiddenPropertyName::detail());
- if (value.IsEmpty()) {
- value = serialized->deserialize();
- info.Holder()->SetHiddenValue(V8HiddenPropertyName::detail(), value);
- }
- v8SetReturnValue(info, value);
+ CustomEvent* event = V8CustomEvent::toNative(info.Holder());
+
+ v8::Handle<v8::Value> result = info.Holder()->GetHiddenValue(V8HiddenPropertyName::detail());
+
+ if (!result.IsEmpty()) {
+ v8SetReturnValue(info, result);
return;
}
- v8SetReturnValue(info, imp->detail().v8Value());
+
+ SerializedScriptValue* serialized = event->serializedScriptValue();
+ if (serialized) {
+ result = serialized->deserialize();
+ v8SetReturnValue(info, cacheState(info.Holder(), result));
+ return;
+ }
+
+ v8SetReturnValue(info, cacheState(info.Holder(), v8::Null(info.GetIsolate())));
+}
+
+void V8CustomEvent::initCustomEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ CustomEvent* event = V8CustomEvent::toNative(args.Holder());
+ ASSERT(!event->serializedScriptValue());
+
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, typeArg, args[0]);
+ V8TRYCATCH_VOID(bool, canBubbleArg, args[1]->BooleanValue());
+ V8TRYCATCH_VOID(bool, cancelableArg, args[2]->BooleanValue());
+ v8::Handle<v8::Value> detailsArg = args[3];
+
+ args.Holder()->SetHiddenValue(V8HiddenPropertyName::detail(), detailsArg);
+ event->initEvent(typeArg, canBubbleArg, cancelableArg);
}
} // namespace WebCore
diff --git a/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp b/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp
index 61a736e..bf99bfb 100644
--- a/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp
+++ b/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp
@@ -87,7 +87,7 @@
v8::Handle<v8::Value> retval = ScriptController::callFunctionWithInstrumentation(0, function, m_resolver, argc, argv);
- // Eat exceptions from namespace resolver and return an empty string. This will most likely cause NAMESPACE_ERR.
+ // Eat exceptions from namespace resolver and return an empty string. This will most likely cause NamespaceError.
if (tryCatch.HasCaught())
return String();
diff --git a/Source/bindings/v8/custom/V8DataViewCustom.cpp b/Source/bindings/v8/custom/V8DataViewCustom.cpp
index b8120e9..4988fdb 100644
--- a/Source/bindings/v8/custom/V8DataViewCustom.cpp
+++ b/Source/bindings/v8/custom/V8DataViewCustom.cpp
@@ -39,7 +39,7 @@
// 'new DataView()' and the call used to construct the cached DataView object.
RefPtr<DataView> dataView = DataView::create(0);
v8::Handle<v8::Object> wrapper = args.Holder();
- V8DOMWrapper::associateObjectWithWrapper(dataView.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
+ V8DOMWrapper::associateObjectWithWrapper<V8DataView>(dataView.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
args.GetReturnValue().Set(wrapper);
return;
}
@@ -47,7 +47,7 @@
throwTypeError(0, args.GetIsolate());
return;
}
- constructWebGLArrayWithArrayBufferArgument<DataView, char>(args, &info, v8::kExternalByteArray, false);
+ constructWebGLArrayWithArrayBufferArgument<DataView, char, V8DataView>(args, &info, v8::kExternalByteArray, false);
}
// FIXME: Don't need this override.
diff --git a/Source/bindings/v8/custom/V8DocumentCustom.cpp b/Source/bindings/v8/custom/V8DocumentCustom.cpp
index 45a5932..1df4fde 100644
--- a/Source/bindings/v8/custom/V8DocumentCustom.cpp
+++ b/Source/bindings/v8/custom/V8DocumentCustom.cpp
@@ -31,16 +31,6 @@
#include "config.h"
#include "V8Document.h"
-#include "bindings/v8/ScriptController.h"
-#include "core/dom/Document.h"
-#include "core/dom/ExceptionCode.h"
-#include "core/dom/Node.h"
-#include "core/dom/TouchList.h"
-#include "core/html/canvas/CanvasRenderingContext.h"
-#include "core/page/Frame.h"
-#include "core/xml/XPathNSResolver.h"
-#include "core/xml/XPathResult.h"
-
#include "V8CanvasRenderingContext2D.h"
#include "V8DOMImplementation.h"
#include "V8HTMLDocument.h"
@@ -51,11 +41,20 @@
#include "V8WebGLRenderingContext.h"
#include "V8XPathNSResolver.h"
#include "V8XPathResult.h"
+#include "bindings/v8/ScriptController.h"
#include "bindings/v8/V8Binding.h"
#include "bindings/v8/V8DOMWrapper.h"
#include "bindings/v8/V8WindowShell.h"
#include "bindings/v8/custom/V8CustomXPathNSResolver.h"
-
+#include "core/dom/Document.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/dom/Node.h"
+#include "core/dom/TouchList.h"
+#include "core/html/canvas/CanvasRenderingContext.h"
+#include "core/page/Frame.h"
+#include "core/xml/DocumentXPathEvaluator.h"
+#include "core/xml/XPathNSResolver.h"
+#include "core/xml/XPathResult.h"
#include "wtf/RefPtr.h"
namespace WebCore {
@@ -71,7 +70,7 @@
RefPtr<XPathNSResolver> resolver = toXPathNSResolver(args[2], args.GetIsolate());
if (!resolver && !args[2]->IsNull() && !args[2]->IsUndefined()) {
- setDOMException(TYPE_MISMATCH_ERR, args.GetIsolate());
+ setDOMException(TypeMismatchError, args.GetIsolate());
return;
}
@@ -80,7 +79,7 @@
if (V8XPathResult::HasInstance(args[4], args.GetIsolate(), worldType(args.GetIsolate())))
inResult = V8XPathResult::toNative(v8::Handle<v8::Object>::Cast(args[4]));
- V8TRYCATCH_VOID(RefPtr<XPathResult>, result, document->evaluate(expression, contextNode.get(), resolver.get(), type, inResult.get(), ec));
+ V8TRYCATCH_VOID(RefPtr<XPathResult>, result, DocumentXPathEvaluator::evaluate(document.get(), expression, contextNode.get(), resolver.get(), type, inResult.get(), ec));
if (ec) {
setDOMException(ec, args.GetIsolate());
return;
diff --git a/Source/bindings/v8/custom/V8FileReaderCustom.cpp b/Source/bindings/v8/custom/V8FileReaderCustom.cpp
index 12cd505..49ea526 100644
--- a/Source/bindings/v8/custom/V8FileReaderCustom.cpp
+++ b/Source/bindings/v8/custom/V8FileReaderCustom.cpp
@@ -32,8 +32,8 @@
#include "V8FileReader.h"
-#include "V8ArrayBuffer.h"
#include "bindings/v8/V8Binding.h"
+#include "bindings/v8/custom/V8ArrayBufferCustom.h"
#include "core/dom/ScriptExecutionContext.h"
namespace WebCore {
@@ -46,7 +46,7 @@
v8SetReturnValue(info, toV8Fast(imp->arrayBufferResult(), info, imp));
return;
}
- v8SetReturnValue(info, v8StringOrNull(imp->stringResult(), info.GetIsolate()));
+ v8SetReturnValueString(info, imp->stringResult(), info.GetIsolate(), NullStringAsNull);
}
} // namespace WebCore
diff --git a/Source/bindings/v8/custom/V8FormDataCustom.cpp b/Source/bindings/v8/custom/V8FormDataCustom.cpp
index e5bf129..81b9388 100644
--- a/Source/bindings/v8/custom/V8FormDataCustom.cpp
+++ b/Source/bindings/v8/custom/V8FormDataCustom.cpp
@@ -47,7 +47,7 @@
RefPtr<DOMFormData> domFormData = DOMFormData::create(form);
v8::Handle<v8::Object> wrapper = args.Holder();
- V8DOMWrapper::associateObjectWithWrapper(domFormData.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
+ V8DOMWrapper::associateObjectWithWrapper<V8FormData>(domFormData.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
args.GetReturnValue().Set(wrapper);
}
diff --git a/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp b/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp
index b1fe7e0..71d75c5 100644
--- a/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp
+++ b/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp
@@ -40,8 +40,8 @@
namespace WebCore {
-template<class HolderContainer>
-static v8::Handle<v8::Value> getNamedItems(HTMLAllCollection* collection, AtomicString name, const HolderContainer& holder)
+template<class CallbackInfo>
+static v8::Handle<v8::Value> getNamedItems(HTMLAllCollection* collection, AtomicString name, const CallbackInfo& callbackInfo)
{
Vector<RefPtr<Node> > namedItems;
collection->namedItems(name, namedItems);
@@ -50,19 +50,19 @@
return v8Undefined();
if (namedItems.size() == 1)
- return toV8Fast(namedItems.at(0).release(), holder, collection);
+ return toV8Fast(namedItems.at(0).release(), callbackInfo, collection);
// FIXME: HTML5 specification says this should be a HTMLCollection.
// http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmlallcollection
- return toV8Fast(NamedNodesCollection::create(namedItems), holder, collection);
+ return toV8Fast(NamedNodesCollection::create(namedItems), callbackInfo, collection);
}
-template<class HolderContainer>
-static v8::Handle<v8::Value> getItem(HTMLAllCollection* collection, v8::Handle<v8::Value> argument, const HolderContainer& holder)
+template<class CallbackInfo>
+static v8::Handle<v8::Value> getItem(HTMLAllCollection* collection, v8::Handle<v8::Value> argument, const CallbackInfo& callbackInfo)
{
v8::Local<v8::Uint32> index = argument->ToArrayIndex();
if (index.IsEmpty()) {
- v8::Handle<v8::Value> result = getNamedItems(collection, toWebCoreString(argument->ToString()), holder);
+ v8::Handle<v8::Value> result = getNamedItems(collection, toWebCoreString(argument->ToString()), callbackInfo);
if (result.IsEmpty())
return v8::Undefined();
@@ -71,7 +71,7 @@
}
RefPtr<Node> result = collection->item(index->Uint32Value());
- return toV8Fast(result.release(), holder, collection);
+ return toV8Fast(result.release(), callbackInfo, collection);
}
void V8HTMLAllCollection::itemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
diff --git a/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp
index 2d9ef71..c12b6c2 100644
--- a/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp
+++ b/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp
@@ -139,7 +139,7 @@
String result = canvas->toDataURL(type, qualityPtr, ec);
setDOMException(ec, args.GetIsolate());
- v8SetReturnValue(args, v8StringOrUndefined(result, args.GetIsolate()));
+ v8SetReturnValueString(args, result, args.GetIsolate(), NullStringAsUndefined);
}
} // namespace WebCore
diff --git a/Source/bindings/v8/custom/V8HTMLFormControlsCollectionCustom.cpp b/Source/bindings/v8/custom/V8HTMLFormControlsCollectionCustom.cpp
index e3372fa..f2e5af5 100644
--- a/Source/bindings/v8/custom/V8HTMLFormControlsCollectionCustom.cpp
+++ b/Source/bindings/v8/custom/V8HTMLFormControlsCollectionCustom.cpp
@@ -39,8 +39,8 @@
namespace WebCore {
-template<typename HolderContainer>
-static v8::Handle<v8::Value> getNamedItems(HTMLFormControlsCollection* collection, const AtomicString& name, const HolderContainer& holder)
+template<typename CallbackInfo>
+static v8::Handle<v8::Value> getNamedItems(HTMLFormControlsCollection* collection, const AtomicString& name, const CallbackInfo& callbackInfo)
{
Vector<RefPtr<Node> > namedItems;
collection->namedItems(name, namedItems);
@@ -49,9 +49,9 @@
return v8Undefined();
if (namedItems.size() == 1)
- return toV8Fast(namedItems.at(0).release(), holder, collection);
+ return toV8Fast(namedItems.at(0).release(), callbackInfo, collection);
- return toV8Fast(collection->ownerNode()->radioNodeList(name).get(), holder, collection);
+ return toV8Fast(collection->ownerNode()->radioNodeList(name).get(), callbackInfo, collection);
}
void V8HTMLFormControlsCollection::namedItemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
diff --git a/Source/bindings/v8/custom/V8HTMLImageElementConstructor.cpp b/Source/bindings/v8/custom/V8HTMLImageElementConstructor.cpp
index e501753..4704dea 100644
--- a/Source/bindings/v8/custom/V8HTMLImageElementConstructor.cpp
+++ b/Source/bindings/v8/custom/V8HTMLImageElementConstructor.cpp
@@ -82,7 +82,7 @@
RefPtr<HTMLImageElement> image = HTMLImageElement::createForJSConstructor(document, optionalWidth, optionalHeight);
v8::Handle<v8::Object> wrapper = args.Holder();
- V8DOMWrapper::associateObjectWithWrapper(image.release(), &V8HTMLImageElementConstructor::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
+ V8DOMWrapper::associateObjectWithWrapper<V8HTMLImageElement>(image.release(), &V8HTMLImageElementConstructor::info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
v8SetReturnValue(args, wrapper);
}
diff --git a/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp b/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp
index 4781667..414ab57 100644
--- a/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp
+++ b/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp
@@ -45,23 +45,23 @@
namespace WebCore {
-template<typename HolderContainer>
-static void getNamedItems(HTMLOptionsCollection* collection, const AtomicString& name, const HolderContainer& holder)
+template<typename CallbackInfo>
+static void getNamedItems(HTMLOptionsCollection* collection, const AtomicString& name, const CallbackInfo& callbackInfo)
{
Vector<RefPtr<Node> > namedItems;
collection->namedItems(name, namedItems);
if (!namedItems.size()) {
- v8SetReturnValueNull(holder);
+ v8SetReturnValueNull(callbackInfo);
return;
}
if (namedItems.size() == 1) {
- v8SetReturnValue(holder, toV8Fast(namedItems.at(0).release(), holder, collection));
+ v8SetReturnValue(callbackInfo, toV8Fast(namedItems.at(0).release(), callbackInfo, collection));
return;
}
- v8SetReturnValue(holder, toV8Fast(NamedNodesCollection::create(namedItems), holder, collection));
+ v8SetReturnValue(callbackInfo, toV8Fast(NamedNodesCollection::create(namedItems), callbackInfo, collection));
}
void V8HTMLOptionsCollection::namedItemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
@@ -80,7 +80,7 @@
void V8HTMLOptionsCollection::addMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
if (!V8HTMLOptionElement::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate()))) {
- setDOMException(TYPE_MISMATCH_ERR, args.GetIsolate());
+ setDOMException(TypeMismatchError, args.GetIsolate());
return;
}
HTMLOptionsCollection* imp = V8HTMLOptionsCollection::toNative(args.Holder());
@@ -93,7 +93,7 @@
bool ok;
V8TRYCATCH_VOID(int, index, toInt32(args[1], ok));
if (!ok)
- ec = TYPE_MISMATCH_ERR;
+ ec = TypeMismatchError;
else
imp->add(option, index, ec);
}
@@ -111,7 +111,7 @@
ExceptionCode ec = 0;
if (!std::isnan(v) && !std::isinf(v)) {
if (v < 0.0)
- ec = INDEX_SIZE_ERR;
+ ec = IndexSizeError;
else if (v > static_cast<double>(UINT_MAX))
newLength = UINT_MAX;
else
diff --git a/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp b/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp
index a4bf03c..5d67db1 100644
--- a/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp
+++ b/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp
@@ -310,7 +310,7 @@
Database* database = V8Database::toNative(v8::Handle<v8::Object>::Cast(args[0]));
if (database) {
InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder()); {
- v8SetReturnValue(args, v8StringOrUndefined(host->databaseIdImpl(database), args.GetIsolate()));
+ v8SetReturnValueString(args, host->databaseIdImpl(database), args.GetIsolate(), NullStringAsUndefined);
return;
}
}
@@ -323,7 +323,7 @@
Storage* storage = V8Storage::toNative(v8::Handle<v8::Object>::Cast(args[0]));
if (storage) {
InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder());
- v8SetReturnValue(args, v8StringOrUndefined(host->storageIdImpl(storage), args.GetIsolate()));
+ v8SetReturnValueString(args, host->storageIdImpl(storage), args.GetIsolate(), NullStringAsUndefined);
return;
}
}
diff --git a/Source/bindings/v8/custom/V8MessageChannelCustom.cpp b/Source/bindings/v8/custom/V8MessageChannelCustom.cpp
index 475da14..e865215 100644
--- a/Source/bindings/v8/custom/V8MessageChannelCustom.cpp
+++ b/Source/bindings/v8/custom/V8MessageChannelCustom.cpp
@@ -58,7 +58,7 @@
V8HiddenPropertyName::setNamedHiddenReference(wrapper, "port1", toV8(obj->port1(), args.Holder(), args.GetIsolate()));
V8HiddenPropertyName::setNamedHiddenReference(wrapper, "port2", toV8(obj->port2(), args.Holder(), args.GetIsolate()));
- V8DOMWrapper::associateObjectWithWrapper(obj.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
+ V8DOMWrapper::associateObjectWithWrapper<V8MessageChannel>(obj.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
args.GetReturnValue().Set(wrapper);
}
diff --git a/Source/bindings/v8/custom/V8MessageEventCustom.cpp b/Source/bindings/v8/custom/V8MessageEventCustom.cpp
index 0516676..00de25f 100644
--- a/Source/bindings/v8/custom/V8MessageEventCustom.cpp
+++ b/Source/bindings/v8/custom/V8MessageEventCustom.cpp
@@ -32,9 +32,10 @@
#include "V8MessageEvent.h"
#include "bindings/v8/SerializedScriptValue.h"
+#include "bindings/v8/V8HiddenPropertyName.h"
+#include "bindings/v8/custom/V8ArrayBufferCustom.h"
#include "core/dom/MessageEvent.h"
-#include "V8ArrayBuffer.h"
#include "V8Blob.h"
#include "V8MessagePort.h"
#include "V8Window.h"
@@ -49,16 +50,14 @@
v8::Handle<v8::Value> result;
switch (event->dataType()) {
case MessageEvent::DataTypeScriptValue: {
- ScriptValue scriptValue = event->dataAsScriptValue();
- if (scriptValue.hasNoValue())
+ result = info.Holder()->GetHiddenValue(V8HiddenPropertyName::data());
+ if (result.IsEmpty())
result = v8::Null(info.GetIsolate());
- else
- result = scriptValue.v8Value();
break;
}
case MessageEvent::DataTypeSerializedScriptValue:
- if (RefPtr<SerializedScriptValue> serializedValue = event->dataAsSerializedScriptValue()) {
+ if (SerializedScriptValue* serializedValue = event->dataAsSerializedScriptValue()) {
MessagePortArray ports = event->ports();
result = serializedValue->deserialize(info.GetIsolate(), &ports);
} else {
@@ -91,12 +90,12 @@
void V8MessageEvent::initMessageEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
MessageEvent* event = V8MessageEvent::toNative(args.Holder());
- String typeArg = toWebCoreString(args[0]);
- bool canBubbleArg = args[1]->BooleanValue();
- bool cancelableArg = args[2]->BooleanValue();
- ScriptValue dataArg = ScriptValue(args[3]);
- String originArg = toWebCoreString(args[4]);
- String lastEventIdArg = toWebCoreString(args[5]);
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, typeArg, args[0]);
+ V8TRYCATCH_VOID(bool, canBubbleArg, args[1]->BooleanValue());
+ V8TRYCATCH_VOID(bool, cancelableArg, args[2]->BooleanValue());
+ v8::Handle<v8::Value> dataArg = args[3];
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, originArg, args[4]);
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, lastEventIdArg, args[5]);
DOMWindow* sourceArg = 0;
if (args[6]->IsObject()) {
@@ -112,7 +111,8 @@
if (!getMessagePortArray(args[7], *portArray, args.GetIsolate()))
return;
}
- event->initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg, originArg, lastEventIdArg, sourceArg, portArray.release());
+ args.Holder()->SetHiddenValue(V8HiddenPropertyName::data(), dataArg);
+ event->initMessageEvent(typeArg, canBubbleArg, cancelableArg, originArg, lastEventIdArg, sourceArg, portArray.release());
}
void V8MessageEvent::webkitInitMessageEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
diff --git a/Source/bindings/v8/custom/V8MutationObserverCustom.cpp b/Source/bindings/v8/custom/V8MutationObserverCustom.cpp
index 24cc5a2..7547dac 100644
--- a/Source/bindings/v8/custom/V8MutationObserverCustom.cpp
+++ b/Source/bindings/v8/custom/V8MutationObserverCustom.cpp
@@ -60,7 +60,7 @@
RefPtr<MutationCallback> callback = V8MutationCallback::create(v8::Handle<v8::Function>::Cast(arg), context, wrapper, args.GetIsolate());
RefPtr<MutationObserver> observer = MutationObserver::create(callback.release());
- V8DOMWrapper::associateObjectWithWrapper(observer.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
+ V8DOMWrapper::associateObjectWithWrapper<V8MutationObserver>(observer.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
args.GetReturnValue().Set(wrapper);
}
diff --git a/Source/bindings/v8/custom/V8NodeCustom.cpp b/Source/bindings/v8/custom/V8NodeCustom.cpp
index 7b372b6..447fb77 100644
--- a/Source/bindings/v8/custom/V8NodeCustom.cpp
+++ b/Source/bindings/v8/custom/V8NodeCustom.cpp
@@ -49,6 +49,7 @@
#include "bindings/v8/V8AbstractEventListener.h"
#include "bindings/v8/V8Binding.h"
#include "bindings/v8/V8EventListener.h"
+#include "core/dom/CustomElementCallbackDispatcher.h"
#include "core/dom/Document.h"
#include "core/dom/EventListener.h"
#include "core/dom/shadow/ShadowRoot.h"
@@ -61,19 +62,17 @@
{
v8::Handle<v8::Object> holder = args.Holder();
Node* imp = V8Node::toNative(holder);
+
+ CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
+
ExceptionCode ec = 0;
Node* newChild = V8Node::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
Node* refChild = V8Node::HasInstance(args[1], args.GetIsolate(), worldType(args.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0;
- bool success = imp->insertBefore(newChild, refChild, ec, AttachLazily);
- if (ec) {
+ imp->insertBefore(newChild, refChild, ec, AttachLazily);
+ if (ec)
setDOMException(ec, args.GetIsolate());
- return;
- }
- if (success) {
+ else
v8SetReturnValue(args, args[0]);
- return;
- }
- v8SetReturnValueNull(args);
}
// This function is customized to take advantage of the optional 4th argument: AttachBehavior
@@ -81,37 +80,33 @@
{
v8::Handle<v8::Object> holder = args.Holder();
Node* imp = V8Node::toNative(holder);
+
+ CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
+
ExceptionCode ec = 0;
Node* newChild = V8Node::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
Node* oldChild = V8Node::HasInstance(args[1], args.GetIsolate(), worldType(args.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0;
- bool success = imp->replaceChild(newChild, oldChild, ec, AttachLazily);
- if (ec) {
+ imp->replaceChild(newChild, oldChild, ec, AttachLazily);
+ if (ec)
setDOMException(ec, args.GetIsolate());
- return;
- }
- if (success) {
+ else
v8SetReturnValue(args, args[1]);
- return;
- }
- v8SetReturnValueNull(args);
}
void V8Node::removeChildMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
v8::Handle<v8::Object> holder = args.Holder();
Node* imp = V8Node::toNative(holder);
+
+ CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
+
ExceptionCode ec = 0;
Node* oldChild = V8Node::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
- bool success = imp->removeChild(oldChild, ec);
- if (ec) {
+ imp->removeChild(oldChild, ec);
+ if (ec)
setDOMException(ec, args.GetIsolate());
- return;
- }
- if (success) {
+ else
v8SetReturnValue(args, args[0]);
- return;
- }
- v8SetReturnValueNull(args);
}
// This function is customized to take advantage of the optional 4th argument: AttachBehavior
@@ -119,18 +114,16 @@
{
v8::Handle<v8::Object> holder = args.Holder();
Node* imp = V8Node::toNative(holder);
+
+ CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
+
ExceptionCode ec = 0;
Node* newChild = V8Node::HasInstance(args[0], args.GetIsolate(), worldType(args.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
- bool success = imp->appendChild(newChild, ec, AttachLazily);
- if (ec) {
+ imp->appendChild(newChild, ec, AttachLazily);
+ if (ec)
setDOMException(ec, args.GetIsolate());
- return;
- }
- if (success) {
+ else
v8SetReturnValue(args, args[0]);
- return;
- }
- v8SetReturnValueNull(args);
}
v8::Handle<v8::Object> wrap(Node* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
diff --git a/Source/bindings/v8/custom/V8PopStateEventCustom.cpp b/Source/bindings/v8/custom/V8PopStateEventCustom.cpp
index 2e5d3b7..ba93201 100644
--- a/Source/bindings/v8/custom/V8PopStateEventCustom.cpp
+++ b/Source/bindings/v8/custom/V8PopStateEventCustom.cpp
@@ -56,11 +56,6 @@
}
PopStateEvent* event = V8PopStateEvent::toNative(info.Holder());
- if (!event->state().hasNoValue()) {
- v8SetReturnValue(info, cacheState(info.Holder(), event->state().v8Value()));
- return;
- }
-
History* history = event->history();
if (!history || !event->serializedState()) {
v8SetReturnValue(info, cacheState(info.Holder(), v8::Null(info.GetIsolate())));
@@ -73,7 +68,7 @@
// The current history state object might've changed in the meantime, so we need to take care
// of using the correct one, and always share the same deserialization with history.state.
- bool isSameState = history->isSameAsCurrentState(event->serializedState().get());
+ bool isSameState = history->isSameAsCurrentState(event->serializedState());
if (isSameState) {
v8::Handle<v8::Object> v8History = toV8Fast(history, info, event).As<v8::Object>();
diff --git a/Source/bindings/v8/custom/V8PromiseCustom.cpp b/Source/bindings/v8/custom/V8PromiseCustom.cpp
index c711a30..8253f04 100644
--- a/Source/bindings/v8/custom/V8PromiseCustom.cpp
+++ b/Source/bindings/v8/custom/V8PromiseCustom.cpp
@@ -51,28 +51,6 @@
namespace {
-int promiseFulfillCallbackTag = 0;
-int promiseResolveCallbackTag = 0;
-int promiseRejectCallbackTag = 0;
-
-v8::Local<v8::Function> getFunction(v8::FunctionCallback callback, int* tag, v8::Isolate* isolate)
-{
- // tag must be a pointer of one of the above tags.
- ASSERT(tag == &promiseFulfillCallbackTag
- || tag == &promiseResolveCallbackTag
- || tag == &promiseRejectCallbackTag);
- WrapperWorldType worldType = WebCore::worldType(isolate);
- V8PerIsolateData* data = V8PerIsolateData::from(isolate);
- ASSERT(data);
- V8PerIsolateData::TemplateMap::iterator result = data->templateMap(worldType).find(tag);
- if (result != data->templateMap(worldType).end())
- return result->value.newLocal(isolate)->GetFunction();
-
- v8::Handle<v8::FunctionTemplate> functionTemplate = v8::FunctionTemplate::New(callback);
- data->templateMap(worldType).add(tag, UnsafePersistent<v8::FunctionTemplate>(isolate, functionTemplate));
- return functionTemplate->GetFunction();
-}
-
class PromiseTask : public ScriptExecutionContext::Task {
public:
PromiseTask(v8::Handle<v8::Function> callback, v8::Handle<v8::Object> receiver, v8::Handle<v8::Value> result)
@@ -119,86 +97,76 @@
return v8::Undefined(isolate);
}
-// This function must have the resolver as the first argument when called
-// See promiseCallback.
+void wrapperCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ ASSERT(!args.Data().IsEmpty());
+ v8::Local<v8::Object> environment = args.Data().As<v8::Object>();
+ v8::Local<v8::Value> result = v8::Undefined(isolate);
+ if (args.Length() > 0)
+ result = args[0];
+
+ v8::Local<v8::Object> promise = environment->GetInternalField(V8PromiseCustom::WrapperCallbackEnvironmentPromiseIndex).As<v8::Object>();
+ v8::Local<v8::Object> resolver = environment->GetInternalField(V8PromiseCustom::WrapperCallbackEnvironmentPromiseResolverIndex).As<v8::Object>();
+ v8::Local<v8::Function> callback = environment->GetInternalField(V8PromiseCustom::WrapperCallbackEnvironmentCallbackIndex).As<v8::Function>();
+
+ v8::Local<v8::Value> argv[] = {
+ result,
+ };
+ v8::TryCatch trycatch;
+ result = V8ScriptRunner::callFunction(callback, getScriptExecutionContext(), promise, WTF_ARRAY_LENGTH(argv), argv);
+ if (result.IsEmpty()) {
+ V8PromiseCustom::rejectResolver(resolver, trycatch.Exception(), V8PromiseCustom::Synchronous, isolate);
+ return;
+ }
+ V8PromiseCustom::resolveResolver(resolver, result, V8PromiseCustom::Synchronous, isolate);
+}
+
+v8::Local<v8::Object> wrapperCallbackEnvironment(v8::Handle<v8::Object> promise, v8::Handle<v8::Object> resolver, v8::Handle<v8::Function> callback)
+{
+ // FIXME: v8::ObjectTemplate::New should be cached.
+ v8::Local<v8::ObjectTemplate> objectTemplate = v8::ObjectTemplate::New();
+ objectTemplate->SetInternalFieldCount(V8PromiseCustom::WrapperCallbackEnvironmentFieldCount);
+ v8::Local<v8::Object> environment = objectTemplate->NewInstance();
+ environment->SetInternalField(V8PromiseCustom::WrapperCallbackEnvironmentPromiseIndex, promise);
+ environment->SetInternalField(V8PromiseCustom::WrapperCallbackEnvironmentPromiseResolverIndex, resolver);
+ environment->SetInternalField(V8PromiseCustom::WrapperCallbackEnvironmentCallbackIndex, callback);
+ return environment;
+}
+
void promiseFulfillCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
{
- v8::Local<v8::Object> resolver;
+ ASSERT(!args.Data().IsEmpty());
+ v8::Local<v8::Object> resolver = args.Data().As<v8::Object>();
v8::Local<v8::Value> result = v8::Undefined(args.GetIsolate());
- ASSERT(args.Length() > 0);
- resolver = args[0].As<v8::Object>();
- if (args.Length() > 1)
- result = args[1];
+ if (args.Length() > 0)
+ result = args[0];
V8PromiseCustom::fulfillResolver(resolver, result, V8PromiseCustom::Synchronous, args.GetIsolate());
}
-// This function must be bound with the resolver as the first argument.
-// See promiseCallback.
void promiseResolveCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
{
- v8::Local<v8::Object> resolver;
+ ASSERT(!args.Data().IsEmpty());
+ v8::Local<v8::Object> resolver = args.Data().As<v8::Object>();
v8::Local<v8::Value> result = v8::Undefined(args.GetIsolate());
- ASSERT(args.Length() > 0);
- resolver = args[0].As<v8::Object>();
- if (args.Length() > 1)
- result = args[1];
+ if (args.Length() > 0)
+ result = args[0];
V8PromiseCustom::resolveResolver(resolver, result, V8PromiseCustom::Synchronous, args.GetIsolate());
}
-// This function must be bound with the resolver as the first argument.
-// See promiseCallback.
void promiseRejectCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
{
- v8::Local<v8::Object> resolver;
+ ASSERT(!args.Data().IsEmpty());
+ v8::Local<v8::Object> resolver = args.Data().As<v8::Object>();
v8::Local<v8::Value> result = v8::Undefined(args.GetIsolate());
- ASSERT(args.Length() > 0);
- resolver = args[0].As<v8::Object>();
- if (args.Length() > 1)
- result = args[1];
+ if (args.Length() > 0)
+ result = args[0];
V8PromiseCustom::rejectResolver(resolver, result, V8PromiseCustom::Synchronous, args.GetIsolate());
}
-v8::Local<v8::Function> promiseCallback(v8::Handle<v8::Object> resolver, V8PromiseCustom::PromiseAlgorithm algorithm, v8::Isolate* isolate)
-{
- v8::Local<v8::Function> callback;
- switch (algorithm) {
- case V8PromiseCustom::FulfillAlgorithm:
- callback = getFunction(promiseFulfillCallback, &promiseFulfillCallbackTag, isolate);
- break;
- case V8PromiseCustom::ResolveAlgorithm:
- callback = getFunction(promiseResolveCallback, &promiseResolveCallbackTag, isolate);
- break;
- case V8PromiseCustom::RejectAlgorithm:
- callback = getFunction(promiseRejectCallback, &promiseRejectCallbackTag, isolate);
- break;
- default:
- ASSERT(0);
- }
- // We bind |resolver| to promise{Fulfill, Resolve, Reject}Callback.
- //
- // promiseCallback(result) will be evaluated as
- // promiseFulfillCallback(resolver, result),
- // if algorithm is FulfillAlgorithm.
-
- // FIXME: If there is a way to bind an object to a function other than evaluate a JavaScript, it will be preferable.
- // We should not depend on the global context that user can change, such as accessing a property, calling a method or so.
- v8::Local<v8::String> script = v8String("(function(f, v1) { return function(v2) { return f(v1, v2); }; })", isolate);
- v8::Local<v8::Value> value = V8ScriptRunner::compileAndRunInternalScript(script, isolate);
-
- v8::Local<v8::Value> argv[] = {
- callback,
- resolver,
- };
- v8::Local<v8::Object> receiver = isolate->GetCurrentContext()->Global();
-
- value = V8ScriptRunner::callFunction(value.As<v8::Function>(), getScriptExecutionContext(), receiver, WTF_ARRAY_LENGTH(argv), argv);
- ASSERT(!value.IsEmpty());
- return value.As<v8::Function>();
-}
-
void callCallbacks(v8::Handle<v8::Array> callbacks, v8::Handle<v8::Value> result, V8PromiseCustom::SynchronousMode mode, v8::Isolate* isolate)
{
v8::Local<v8::Object> global = isolate->GetCurrentContext()->Global();
@@ -209,6 +177,70 @@
}
}
+void promiseEveryFulfillCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ ASSERT(!args.Data().IsEmpty());
+ v8::Local<v8::Object> environment = args.Data().As<v8::Object>();
+ v8::Local<v8::Value> result = v8::Undefined(isolate);
+ if (args.Length() > 0)
+ result = args[0];
+
+ v8::Local<v8::Object> resolver = environment->GetInternalField(V8PromiseCustom::PromiseEveryEnvironmentPromiseResolverIndex).As<v8::Object>();
+ v8::Local<v8::Object> countdownWrapper = environment->GetInternalField(V8PromiseCustom::PromiseEveryEnvironmentCountdownIndex).As<v8::Object>();
+ v8::Local<v8::Integer> index = environment->GetInternalField(V8PromiseCustom::PromiseEveryEnvironmentIndexIndex).As<v8::Integer>();
+ v8::Local<v8::Array> results = environment->GetInternalField(V8PromiseCustom::PromiseEveryEnvironmentResultsIndex).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::resolveResolver(resolver, results, V8PromiseCustom::Synchronous, isolate);
+ return;
+ }
+ countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex, v8::Integer::New(countdown->Value() - 1));
+}
+
+void promiseSomeRejectCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ ASSERT(!args.Data().IsEmpty());
+ v8::Local<v8::Object> environment = args.Data().As<v8::Object>();
+ v8::Local<v8::Value> result = v8::Undefined(isolate);
+ if (args.Length() > 0)
+ result = args[0];
+
+ v8::Local<v8::Object> resolver = environment->GetInternalField(V8PromiseCustom::PromiseEveryEnvironmentPromiseResolverIndex).As<v8::Object>();
+ v8::Local<v8::Object> countdownWrapper = environment->GetInternalField(V8PromiseCustom::PromiseEveryEnvironmentCountdownIndex).As<v8::Object>();
+ v8::Local<v8::Integer> index = environment->GetInternalField(V8PromiseCustom::PromiseEveryEnvironmentIndexIndex).As<v8::Integer>();
+ v8::Local<v8::Array> results = environment->GetInternalField(V8PromiseCustom::PromiseEveryEnvironmentResultsIndex).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::rejectResolver(resolver, results, V8PromiseCustom::Synchronous, isolate);
+ return;
+ }
+ countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex, v8::Integer::New(countdown->Value() - 1));
+}
+
+v8::Local<v8::Object> promiseEveryEnvironment(v8::Handle<v8::Object> resolver, v8::Handle<v8::Object> countdownWrapper, int index, v8::Handle<v8::Array> results, v8::Isolate* isolate)
+{
+ // FIXME: v8::ObjectTemplate::New should be cached.
+ v8::Local<v8::ObjectTemplate> objectTemplate = v8::ObjectTemplate::New();
+ objectTemplate->SetInternalFieldCount(V8PromiseCustom::PromiseEveryEnvironmentFieldCount);
+ v8::Local<v8::Object> environment = objectTemplate->NewInstance();
+
+ environment->SetInternalField(V8PromiseCustom::PromiseEveryEnvironmentPromiseResolverIndex, resolver);
+ environment->SetInternalField(V8PromiseCustom::PromiseEveryEnvironmentCountdownIndex, countdownWrapper);
+ environment->SetInternalField(V8PromiseCustom::PromiseEveryEnvironmentIndexIndex, v8::Integer::New(index));
+ environment->SetInternalField(V8PromiseCustom::PromiseEveryEnvironmentResultsIndex, results);
+ return environment;
+}
+
} // namespace
void V8Promise::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
@@ -235,6 +267,181 @@
return;
}
+void V8Promise::thenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::Function> fulfillWrapper, rejectWrapper;
+ v8::Local<v8::Object> promise, resolver;
+ V8PromiseCustom::createPromise(args.Holder(), &promise, &resolver, isolate);
+ if (args.Length() > 0 && !args[0]->IsUndefined()) {
+ if (!args[0]->IsFunction()) {
+ v8SetReturnValue(args, throwTypeError("fulfillCallback must be a function or undefined", isolate));
+ return;
+ }
+ fulfillWrapper = createClosure(wrapperCallback, wrapperCallbackEnvironment(promise, resolver, args[0].As<v8::Function>()));
+ } else {
+ fulfillWrapper = createClosure(promiseFulfillCallback, resolver);
+ }
+ if (args.Length() > 1 && !args[1]->IsUndefined()) {
+ if (!args[1]->IsFunction()) {
+ v8SetReturnValue(args, throwTypeError("rejectCallback must be a function or undefined", isolate));
+ return;
+ }
+ rejectWrapper = createClosure(wrapperCallback, wrapperCallbackEnvironment(promise, resolver, args[1].As<v8::Function>()));
+ } else {
+ rejectWrapper = createClosure(promiseRejectCallback, resolver);
+ }
+ V8PromiseCustom::append(args.Holder(), fulfillWrapper, rejectWrapper, isolate);
+ v8SetReturnValue(args, promise);
+}
+
+void V8Promise::catchMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::Function> fulfillWrapper, rejectWrapper;
+ v8::Local<v8::Object> promise, resolver;
+ V8PromiseCustom::createPromise(args.Holder(), &promise, &resolver, isolate);
+
+ if (args.Length() > 0 && !args[0]->IsUndefined()) {
+ if (!args[0]->IsFunction()) {
+ v8SetReturnValue(args, throwTypeError("rejectCallback must be a function or undefined", isolate));
+ return;
+ }
+ rejectWrapper = createClosure(wrapperCallback, wrapperCallbackEnvironment(promise, resolver, args[0].As<v8::Function>()));
+ } else {
+ rejectWrapper = createClosure(promiseRejectCallback, resolver);
+ }
+ fulfillWrapper = createClosure(promiseFulfillCallback, resolver);
+ V8PromiseCustom::append(args.Holder(), fulfillWrapper, rejectWrapper, isolate);
+ v8SetReturnValue(args, promise);
+}
+
+void V8Promise::fulfillMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::Value> result = v8::Undefined(isolate);
+ if (args.Length() > 0)
+ result = args[0];
+
+ v8::Local<v8::Object> promise, resolver;
+ V8PromiseCustom::createPromise(args.Holder(), &promise, &resolver, isolate);
+ V8PromiseCustom::fulfillResolver(resolver, result, V8PromiseCustom::Asynchronous, isolate);
+ v8SetReturnValue(args, promise);
+}
+
+void V8Promise::resolveMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::Value> result = v8::Undefined(isolate);
+ if (args.Length() > 0)
+ result = args[0];
+
+ v8::Local<v8::Object> promise, resolver;
+ V8PromiseCustom::createPromise(args.Holder(), &promise, &resolver, isolate);
+ V8PromiseCustom::resolveResolver(resolver, result, V8PromiseCustom::Asynchronous, isolate);
+ v8SetReturnValue(args, promise);
+}
+
+void V8Promise::rejectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::Value> result = v8::Undefined(isolate);
+ if (args.Length() > 0)
+ result = args[0];
+
+ v8::Local<v8::Object> promise, resolver;
+ V8PromiseCustom::createPromise(args.Holder(), &promise, &resolver, isolate);
+ V8PromiseCustom::rejectResolver(resolver, result, V8PromiseCustom::Asynchronous, isolate);
+ v8SetReturnValue(args, promise);
+}
+
+void V8Promise::anyMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::Object> promise, resolver;
+ V8PromiseCustom::createPromise(args.Holder(), &promise, &resolver, isolate);
+
+ if (!args.Length()) {
+ V8PromiseCustom::resolveResolver(resolver, v8::Undefined(isolate), V8PromiseCustom::Asynchronous, isolate);
+ v8SetReturnValue(args, promise);
+ return;
+ }
+
+ v8::Local<v8::Function> fulfillCallback = createClosure(promiseResolveCallback, resolver);
+ v8::Local<v8::Function> rejectCallback = createClosure(promiseRejectCallback, resolver);
+
+ for (int i = 0; i < args.Length(); ++i) {
+ v8::Local<v8::Object> eachPromise, eachResolver;
+ V8PromiseCustom::createPromise(args.Holder(), &eachPromise, &eachResolver, isolate);
+ V8PromiseCustom::resolveResolver(eachResolver, args[i], V8PromiseCustom::Asynchronous, isolate);
+ V8PromiseCustom::append(eachPromise, fulfillCallback, rejectCallback, isolate);
+ }
+ v8SetReturnValue(args, promise);
+}
+
+void V8Promise::everyMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::Object> promise, resolver;
+ V8PromiseCustom::createPromise(args.Holder(), &promise, &resolver, isolate);
+
+ if (!args.Length()) {
+ V8PromiseCustom::resolveResolver(resolver, v8::Undefined(isolate), V8PromiseCustom::Asynchronous, isolate);
+ v8SetReturnValue(args, promise);
+ return;
+ }
+
+ // FIXME: v8::ObjectTemplate::New should be cached.
+ v8::Local<v8::ObjectTemplate> objectTemplate = v8::ObjectTemplate::New();
+ objectTemplate->SetInternalFieldCount(V8PromiseCustom::PrimitiveWrapperFieldCount);
+ v8::Local<v8::Object> countdownWrapper = objectTemplate->NewInstance();
+ countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex, v8::Integer::New(args.Length()));
+ v8::Local<v8::Array> results = v8::Array::New();
+
+ v8::Local<v8::Function> rejectCallback = createClosure(promiseRejectCallback, resolver);
+ for (int i = 0; i < args.Length(); ++i) {
+ v8::Local<v8::Object> environment = promiseEveryEnvironment(resolver, countdownWrapper, i, results, isolate);
+ v8::Local<v8::Function> fulfillCallback = v8::FunctionTemplate::New(promiseEveryFulfillCallback, environment)->GetFunction();
+ v8::Local<v8::Object> eachPromise, eachResolver;
+ V8PromiseCustom::createPromise(args.Holder(), &eachPromise, &eachResolver, isolate);
+ V8PromiseCustom::resolveResolver(eachResolver, args[i], V8PromiseCustom::Asynchronous, isolate);
+ V8PromiseCustom::append(eachPromise, fulfillCallback, rejectCallback, isolate);
+ }
+ v8SetReturnValue(args, promise);
+}
+
+void V8Promise::someMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::Object> promise, resolver;
+ V8PromiseCustom::createPromise(args.Holder(), &promise, &resolver, isolate);
+
+ if (!args.Length()) {
+ V8PromiseCustom::resolveResolver(resolver, v8::Undefined(isolate), V8PromiseCustom::Asynchronous, isolate);
+ v8SetReturnValue(args, promise);
+ return;
+ }
+
+ // Promise.some also uses PromiseEveryEnvironment.
+ // FIXME: v8::ObjectTemplate::New should be cached.
+ v8::Local<v8::ObjectTemplate> objectTemplate = v8::ObjectTemplate::New();
+ objectTemplate->SetInternalFieldCount(V8PromiseCustom::PrimitiveWrapperFieldCount);
+ v8::Local<v8::Object> countdownWrapper = objectTemplate->NewInstance();
+ countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex, v8::Integer::New(args.Length()));
+ v8::Local<v8::Array> results = v8::Array::New();
+
+ v8::Local<v8::Function> fulfillCallback = createClosure(promiseResolveCallback, resolver);
+ for (int i = 0; i < args.Length(); ++i) {
+ v8::Local<v8::Object> environment = promiseEveryEnvironment(resolver, countdownWrapper, i, results, isolate);
+ v8::Local<v8::Object> eachPromise, eachResolver;
+ v8::Local<v8::Function> rejectCallback = v8::FunctionTemplate::New(promiseSomeRejectCallback, environment)->GetFunction();
+ V8PromiseCustom::createPromise(args.Holder(), &eachPromise, &eachResolver, isolate);
+ V8PromiseCustom::resolveResolver(eachResolver, args[i], V8PromiseCustom::Asynchronous, isolate);
+ V8PromiseCustom::append(eachPromise, fulfillCallback, rejectCallback, isolate);
+ }
+ v8SetReturnValue(args, promise);
+}
+
//
// -- V8PromiseCustom --
void V8PromiseCustom::createPromise(v8::Handle<v8::Object> creationContext, v8::Local<v8::Object>* promise, v8::Local<v8::Object>* resolver, v8::Isolate* isolate)
@@ -283,8 +490,8 @@
ASSERT(result->IsObject());
v8::TryCatch trycatch;
v8::Handle<v8::Value> argv[] = {
- promiseCallback(resolver, ResolveAlgorithm, isolate),
- promiseCallback(resolver, RejectAlgorithm, isolate),
+ createClosure(promiseResolveCallback, resolver),
+ createClosure(promiseRejectCallback, resolver),
};
if (V8ScriptRunner::callFunction(then.As<v8::Function>(), getScriptExecutionContext(), result.As<v8::Object>(), WTF_ARRAY_LENGTH(argv), argv).IsEmpty())
rejectResolver(resolver, trycatch.Exception(), mode, isolate);
diff --git a/Source/bindings/v8/custom/V8PromiseCustom.h b/Source/bindings/v8/custom/V8PromiseCustom.h
index 066d105..930f3f6 100644
--- a/Source/bindings/v8/custom/V8PromiseCustom.h
+++ b/Source/bindings/v8/custom/V8PromiseCustom.h
@@ -39,10 +39,24 @@
InternalFieldCount, // This entry must always be at the bottom.
};
- enum PromiseAlgorithm {
- FulfillAlgorithm,
- ResolveAlgorithm,
- RejectAlgorithm,
+ enum WrapperCallbackEnvironmentFieldIndex {
+ WrapperCallbackEnvironmentPromiseIndex,
+ WrapperCallbackEnvironmentPromiseResolverIndex,
+ WrapperCallbackEnvironmentCallbackIndex,
+ WrapperCallbackEnvironmentFieldCount, // This entry must always be at the bottom.
+ };
+
+ enum PromiseEveryEnvironmentFieldIndex {
+ PromiseEveryEnvironmentPromiseResolverIndex,
+ PromiseEveryEnvironmentCountdownIndex,
+ PromiseEveryEnvironmentIndexIndex,
+ PromiseEveryEnvironmentResultsIndex,
+ PromiseEveryEnvironmentFieldCount, // This entry must always be at the bottom.
+ };
+
+ enum PrimitiveWrapperFieldIndex {
+ PrimitiveWrapperPrimitiveIndex,
+ PrimitiveWrapperFieldCount, // This entry must always be at the bottom.
};
enum PromiseState {
diff --git a/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp b/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp
index a2dd7c6..1c2787f 100644
--- a/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp
+++ b/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp
@@ -47,7 +47,7 @@
void V8SQLTransaction::executeSqlMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
if (!args.Length()) {
- setDOMException(SYNTAX_ERR, args.GetIsolate());
+ setDOMException(SyntaxError, args.GetIsolate());
return;
}
@@ -57,7 +57,7 @@
if (args.Length() > 1 && !isUndefinedOrNull(args[1])) {
if (!args[1]->IsObject()) {
- setDOMException(TYPE_MISMATCH_ERR, args.GetIsolate());
+ setDOMException(TypeMismatchError, args.GetIsolate());
return;
}
@@ -93,7 +93,7 @@
RefPtr<SQLStatementCallback> callback;
if (args.Length() > 2 && !isUndefinedOrNull(args[2])) {
if (!args[2]->IsObject()) {
- setDOMException(TYPE_MISMATCH_ERR, args.GetIsolate());
+ setDOMException(TypeMismatchError, args.GetIsolate());
return;
}
callback = V8SQLStatementCallback::create(args[2], scriptExecutionContext);
@@ -102,7 +102,7 @@
RefPtr<SQLStatementErrorCallback> errorCallback;
if (args.Length() > 3 && !isUndefinedOrNull(args[3])) {
if (!args[3]->IsObject()) {
- setDOMException(TYPE_MISMATCH_ERR, args.GetIsolate());
+ setDOMException(TypeMismatchError, args.GetIsolate());
return;
}
errorCallback = V8SQLStatementErrorCallback::create(args[3], scriptExecutionContext);
diff --git a/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp b/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp
index f238688..ab35678 100644
--- a/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp
+++ b/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp
@@ -33,6 +33,7 @@
#include "V8SQLTransactionSync.h"
#include "V8SQLResultSet.h"
+#include "bindings/v8/ExceptionState.h"
#include "bindings/v8/V8Binding.h"
#include "core/dom/ExceptionCode.h"
#include "core/platform/sql/SQLValue.h"
@@ -47,7 +48,7 @@
void V8SQLTransactionSync::executeSqlMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
{
if (!args.Length()) {
- setDOMException(SYNTAX_ERR, args.GetIsolate());
+ setDOMException(SyntaxError, args.GetIsolate());
return;
}
@@ -57,7 +58,7 @@
if (args.Length() > 1 && !isUndefinedOrNull(args[1])) {
if (!args[1]->IsObject()) {
- setDOMException(TYPE_MISMATCH_ERR, args.GetIsolate());
+ setDOMException(TypeMismatchError, args.GetIsolate());
return;
}
@@ -88,9 +89,10 @@
SQLTransactionSync* transaction = V8SQLTransactionSync::toNative(args.Holder());
- ExceptionCode ec = 0;
- v8::Handle<v8::Value> result = toV8Fast(transaction->executeSQL(statement, sqlValues, ec), args, transaction);
- setDOMException(ec, args.GetIsolate());
+ ExceptionState es(args.GetIsolate());
+ v8::Handle<v8::Value> result = toV8Fast(transaction->executeSQL(statement, sqlValues, es), args, transaction);
+ if (es.throwIfNeeded())
+ return;
v8SetReturnValue(args, result);
}
diff --git a/Source/bindings/v8/custom/V8SVGLengthCustom.cpp b/Source/bindings/v8/custom/V8SVGLengthCustom.cpp
index 7ba0664..1202334 100644
--- a/Source/bindings/v8/custom/V8SVGLengthCustom.cpp
+++ b/Source/bindings/v8/custom/V8SVGLengthCustom.cpp
@@ -57,7 +57,7 @@
{
SVGPropertyTearOff<SVGLength>* wrapper = V8SVGLength::toNative(info.Holder());
if (wrapper->isReadOnly()) {
- setDOMException(NO_MODIFICATION_ALLOWED_ERR, info.GetIsolate());
+ setDOMException(NoModificationAllowedError, info.GetIsolate());
return;
}
@@ -80,7 +80,7 @@
{
SVGPropertyTearOff<SVGLength>* wrapper = V8SVGLength::toNative(args.Holder());
if (wrapper->isReadOnly()) {
- setDOMException(NO_MODIFICATION_ALLOWED_ERR, args.GetIsolate());
+ setDOMException(NoModificationAllowedError, args.GetIsolate());
return;
}
diff --git a/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp b/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp
index 7564402..2e8923f 100644
--- a/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp
+++ b/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp
@@ -596,7 +596,7 @@
float* data = jsArrayToFloatArray(array, len);
if (!data) {
// FIXME: consider different / better exception type.
- setDOMException(SYNTAX_ERR, args.GetIsolate());
+ setDOMException(SyntaxError, args.GetIsolate());
return;
}
ExceptionCode ec = 0;
@@ -671,7 +671,7 @@
int* data = jsArrayToIntArray(array, len);
if (!data) {
// FIXME: consider different / better exception type.
- setDOMException(SYNTAX_ERR, args.GetIsolate());
+ setDOMException(SyntaxError, args.GetIsolate());
return;
}
ExceptionCode ec = 0;
@@ -782,7 +782,7 @@
float* data = jsArrayToFloatArray(array, len);
if (!data) {
// FIXME: consider different / better exception type.
- setDOMException(SYNTAX_ERR, args.GetIsolate());
+ setDOMException(SyntaxError, args.GetIsolate());
return;
}
ExceptionCode ec = 0;
diff --git a/Source/bindings/v8/custom/V8WebKitPointCustom.cpp b/Source/bindings/v8/custom/V8WebKitPointCustom.cpp
index 98329cc..00d640f 100644
--- a/Source/bindings/v8/custom/V8WebKitPointCustom.cpp
+++ b/Source/bindings/v8/custom/V8WebKitPointCustom.cpp
@@ -57,7 +57,7 @@
}
RefPtr<DOMPoint> point = DOMPoint::create(x, y);
v8::Handle<v8::Object> wrapper = args.Holder();
- V8DOMWrapper::associateObjectWithWrapper(point.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
+ V8DOMWrapper::associateObjectWithWrapper<V8WebKitPoint>(point.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
args.GetReturnValue().Set(wrapper);
}
diff --git a/Source/bindings/v8/custom/V8WindowCustom.cpp b/Source/bindings/v8/custom/V8WindowCustom.cpp
index 7dac11f..ae23d16 100644
--- a/Source/bindings/v8/custom/V8WindowCustom.cpp
+++ b/Source/bindings/v8/custom/V8WindowCustom.cpp
@@ -80,7 +80,7 @@
ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>(imp->document());
if (!scriptContext) {
- setDOMException(INVALID_ACCESS_ERR, args.GetIsolate());
+ setDOMException(InvalidAccessError, args.GetIsolate());
return;
}
@@ -232,60 +232,6 @@
info.This()->Set(name, value);
}
-void V8Window::addEventListenerMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
-{
- String eventType = toWebCoreString(args[0]);
- bool useCapture = args[2]->BooleanValue();
-
- DOMWindow* imp = V8Window::toNative(args.Holder());
-
- if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame()))
- return;
-
- Document* doc = imp->document();
-
- if (!doc)
- return;
-
- // FIXME: Check if there is not enough arguments
- if (!imp->frame())
- return;
-
- RefPtr<EventListener> listener = V8EventListenerList::getEventListener(args[1], false, ListenerFindOrCreate);
-
- if (listener) {
- imp->addEventListener(eventType, listener, useCapture);
- createHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex, args.GetIsolate());
- }
-}
-
-
-void V8Window::removeEventListenerMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
-{
- String eventType = toWebCoreString(args[0]);
- bool useCapture = args[2]->BooleanValue();
-
- DOMWindow* imp = V8Window::toNative(args.Holder());
-
- if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame()))
- return;
-
- Document* doc = imp->document();
-
- if (!doc)
- return;
-
- if (!imp->frame())
- return;
-
- RefPtr<EventListener> listener = V8EventListenerList::getEventListener(args[1], false, ListenerFindOnly);
-
- if (listener) {
- imp->removeEventListener(eventType, listener.get(), useCapture);
- removeHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex, args.GetIsolate());
- }
-}
-
static bool isLegacyTargetOriginDesignation(v8::Handle<v8::Value> value)
{
if (value->IsString() || value->IsStringObject())
@@ -539,17 +485,21 @@
Frame* target = targetWindow->frame();
if (!target)
return false;
- Frame* childFrame = target->tree()->scopedChild(index);
// Notify the loader's client if the initial document has been accessed.
if (target->loader()->stateMachine()->isDisplayingInitialEmptyDocument())
target->loader()->didAccessInitialDocument();
+ Frame* childFrame = target->tree()->scopedChild(index);
+
// Notice that we can't call HasRealNamedProperty for ACCESS_HAS
// because that would generate infinite recursion.
if (type == v8::ACCESS_HAS && childFrame)
return true;
- if (type == v8::ACCESS_GET && childFrame && !host->HasRealIndexedProperty(index))
+ if (type == v8::ACCESS_GET
+ && childFrame
+ && !host->HasRealIndexedProperty(index)
+ && !window->HasRealIndexedProperty(index))
return true;
return BindingSecurity::shouldAllowAccessToFrame(target, DoNotReportSecurityError);
diff --git a/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp b/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp
index 80860e6..5f2526d 100644
--- a/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp
+++ b/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp
@@ -31,7 +31,6 @@
#include "config.h"
#include "V8XMLHttpRequest.h"
-#include "V8ArrayBuffer.h"
#include "V8ArrayBufferView.h"
#include "V8Blob.h"
#include "V8Document.h"
@@ -62,7 +61,7 @@
RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context, securityOrigin);
v8::Handle<v8::Object> wrapper = args.Holder();
- V8DOMWrapper::associateObjectWithWrapper(xmlHttpRequest.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
+ V8DOMWrapper::associateObjectWithWrapper<V8XMLHttpRequest>(xmlHttpRequest.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
args.GetReturnValue().Set(wrapper);
}
@@ -76,7 +75,7 @@
return;
}
if (text.hasNoValue()) {
- v8SetReturnValue(info, v8String(emptyString(), info.GetIsolate()));
+ v8SetReturnValueString(info, emptyString(), info.GetIsolate());
return;
}
v8SetReturnValue(info, text.v8Value());
diff --git a/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp b/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp
index 7a4eae0..509c504 100644
--- a/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp
+++ b/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp
@@ -72,7 +72,7 @@
if (result.isNull())
return;
- v8SetReturnValue(args, v8String(result, args.GetIsolate()));
+ v8SetReturnValueString(args, result, args.GetIsolate());
}
void V8XSLTProcessor::removeParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
diff --git a/Source/bindings/v8/npruntime.cpp b/Source/bindings/v8/npruntime.cpp
index 2acf445..af96ab0 100644
--- a/Source/bindings/v8/npruntime.cpp
+++ b/Source/bindings/v8/npruntime.cpp
@@ -159,6 +159,7 @@
ASSERT(name);
if (name) {
+
StringKey key(name);
StringIdentifierMap* identMap = getStringIdentifierMap();
StringIdentifierMap::iterator iter = identMap->find(key);
@@ -259,8 +260,6 @@
variant->type = NPVariantType_Void;
}
-static void _NPN_RegisterObject(NPObject*, NPP);
-
NPObject *_NPN_CreateObject(NPP npp, NPClass* npClass)
{
ASSERT(npClass);
@@ -274,12 +273,6 @@
npObject->_class = npClass;
npObject->referenceCount = 1;
-
- // TODO(wez): Temporarily allow objects to be created with null owner,
- // until Chrome-side patch to call-sites has landed.
- if (npp)
- _NPN_RegisterObject(npObject, npp);
-
return npObject;
}
@@ -297,8 +290,6 @@
return npObject;
}
-static void _NPN_UnregisterObject(NPObject*);
-
// _NPN_DeallocateObject actually deletes the object. Technically,
// callers should use _NPN_ReleaseObject. Webkit exposes this function
// to kill objects which plugins may not have properly released.
@@ -314,7 +305,6 @@
if (_NPN_IsAlive(npObject))
_NPN_UnregisterObject(npObject);
- ASSERT(!npObject->referenceCount);
npObject->referenceCount = -1;
if (npObject->_class->deallocate)
npObject->_class->deallocate(npObject);
@@ -363,94 +353,107 @@
// with a particular plugin.
typedef WTF::HashSet<NPObject*> NPObjectSet;
-typedef WTF::HashMap<NPObject*, NPP> NPObjectMap;
-typedef WTF::HashMap<NPP, OwnPtr<NPObjectSet> > NPObjectOwnerMap;
+typedef WTF::HashMap<NPObject*, NPObject*> NPObjectMap;
+typedef WTF::HashMap<NPObject*, NPObjectSet*> NPRootObjectMap;
-// A map of live NPObjects to their owner Ids.
+// A map of live NPObjects with pointers to their Roots.
static NPObjectMap& liveObjectMap()
{
DEFINE_STATIC_LOCAL(NPObjectMap, objectMap, ());
return objectMap;
}
-// A map of the owner Ids and the list of NPObjects
-// associated with each.
-static NPObjectOwnerMap& objectOwnerMap()
+// A map of the root objects and the list of NPObjects
+// associated with that object.
+static NPRootObjectMap& rootObjectMap()
{
- DEFINE_STATIC_LOCAL(NPObjectOwnerMap, ownerMap, ());
- return ownerMap;
+ DEFINE_STATIC_LOCAL(NPRootObjectMap, objectMap, ());
+ return objectMap;
}
-static void _NPN_RegisterObject(NPObject* npObject, NPP owner)
+extern "C" {
+
+void _NPN_RegisterObject(NPObject* npObject, NPObject* owner)
{
ASSERT(npObject);
- ASSERT(owner);
- NPObjectOwnerMap::iterator ownerEntry = objectOwnerMap().find(owner);
- ASSERT(ownerEntry != objectOwnerMap().end());
- ownerEntry->value->add(npObject);
+ // Check if already registered.
+ if (liveObjectMap().find(npObject) != liveObjectMap().end())
+ return;
+
+ if (!owner) {
+ // Registering a new owner object.
+ ASSERT(rootObjectMap().find(npObject) == rootObjectMap().end());
+ rootObjectMap().set(npObject, new NPObjectSet());
+ } else {
+ // Always associate this object with it's top-most parent.
+ // Since we always flatten, we only have to look up one level.
+ NPObjectMap::iterator ownerEntry = liveObjectMap().find(owner);
+ NPObject* parent = 0;
+ if (liveObjectMap().end() != ownerEntry)
+ parent = ownerEntry->value;
+
+ if (parent)
+ owner = parent;
+ ASSERT(rootObjectMap().find(npObject) == rootObjectMap().end());
+ if (rootObjectMap().find(owner) != rootObjectMap().end())
+ rootObjectMap().get(owner)->add(npObject);
+ }
ASSERT(liveObjectMap().find(npObject) == liveObjectMap().end());
liveObjectMap().set(npObject, owner);
}
-static void _NPN_UnregisterObject(NPObject* npObject)
+void _NPN_UnregisterObject(NPObject* npObject)
{
ASSERT(npObject);
ASSERT(liveObjectMap().find(npObject) != liveObjectMap().end());
- NPP owner = liveObjectMap().find(npObject)->value;
- ASSERT(objectOwnerMap().find(owner) != objectOwnerMap().end());
- NPObjectSet* list = objectOwnerMap().find(owner)->value.get();
+ NPObject* owner = 0;
+ if (liveObjectMap().find(npObject) != liveObjectMap().end())
+ owner = liveObjectMap().find(npObject)->value;
- ASSERT(list->find(npObject) != list->end());
- list->remove(npObject);
+ if (!owner) {
+ // Unregistering a owner object; also unregister it's descendants.
+ ASSERT(rootObjectMap().find(npObject) != rootObjectMap().end());
+ NPObjectSet* set = rootObjectMap().get(npObject);
+ while (set->size() > 0) {
+#ifndef NDEBUG
+ int size = set->size();
+#endif
+ NPObject* sub_object = *(set->begin());
+ // The sub-object should not be a owner!
+ ASSERT(rootObjectMap().find(sub_object) == rootObjectMap().end());
+
+ // First, unregister the object.
+ set->remove(sub_object);
+ liveObjectMap().remove(sub_object);
+
+ // Script objects hold a refernce to their DOMWindow*, which is going away if
+ // we're unregistering the associated owner NPObject. Clear it out.
+ if (V8NPObject* v8npObject = npObjectToV8NPObject(sub_object))
+ v8npObject->rootObject = 0;
+
+ // Remove the JS references to the object.
+ forgetV8ObjectForNPObject(sub_object);
+
+ ASSERT(set->size() < size);
+ }
+ delete set;
+ rootObjectMap().remove(npObject);
+ } else {
+ NPRootObjectMap::iterator ownerEntry = rootObjectMap().find(owner);
+ if (ownerEntry != rootObjectMap().end()) {
+ NPObjectSet* list = ownerEntry->value;
+ ASSERT(list->find(npObject) != list->end());
+ list->remove(npObject);
+ }
+ }
liveObjectMap().remove(npObject);
forgetV8ObjectForNPObject(npObject);
}
-extern "C" {
-
-void _NPN_RegisterObjectOwner(NPP owner)
-{
- ASSERT(owner);
-
- if (objectOwnerMap().find(owner) == objectOwnerMap().end())
- objectOwnerMap().set(owner, adoptPtr(new NPObjectSet()));
-}
-
-void _NPN_UnregisterObjectOwner(NPP owner)
-{
- ASSERT(objectOwnerMap().find(owner) != objectOwnerMap().end());
- OwnPtr<NPObjectSet> set = objectOwnerMap().take(owner);
-
- for (NPObjectSet::iterator iter = set->begin(); iter != set->end(); ++iter) {
- NPObject* npObject = *iter;
-
- // First, unregister the object.
- liveObjectMap().remove(npObject);
-
- // Script objects hold a reference to their DOMWindow*, which is going
- // away if we're unregistering the associated owner NPObject. Clear it
- // out.
- // TODO(wez): If the object is no longer "alive", why do we need this?
- if (V8NPObject* v8NpObject = npObjectToV8NPObject(npObject))
- v8NpObject->rootObject = 0;
-
- // Remove the JS references to the object.
- forgetV8ObjectForNPObject(npObject);
- }
-}
-
-NPP _NPN_GetObjectOwner(NPObject* npObject)
-{
- NPObjectMap::iterator i = liveObjectMap().find(npObject);
- if (i != liveObjectMap().end())
- return i->value;
- return 0;
-}
-
bool _NPN_IsAlive(NPObject* npObject)
{
return liveObjectMap().find(npObject) != liveObjectMap().end();
diff --git a/Source/bindings/v8/npruntime_priv.h b/Source/bindings/v8/npruntime_priv.h
index 013b6cc..e799a64 100644
--- a/Source/bindings/v8/npruntime_priv.h
+++ b/Source/bindings/v8/npruntime_priv.h
@@ -55,21 +55,30 @@
// plugin can be destroyed, which can unload the DLL. So, we must eliminate
// all pointers to any object ever created by the plugin.
-// Each plugin is registered as an "object owner", by its unique NPP identifier.
-// When an object passes from a plugin to script, or vice versa, it is
-// registered with the runtime, tagged with its owning plugin's NPP. When the
-// owning plugin is eventually destroyed, its NPP identifier is unregistered
-// from the runtime, and the NPObjects it owns are released - V8 objects that
-// referred to them may remain, but will no longer be scriptable.
+// We generally associate NPObjects with an owner. The owner of an NPObject
+// is an NPObject which, when destroyed, also destroys all objects it owns.
+// For example, if an NPAPI plugin creates 10 sub-NPObjects, all 11 objects
+// (the NPAPI plugin + its 10 sub-objects) should become inaccessible
+// simultaneously.
-// Registers the supplied plugin NPP identifier as a valid object owner.
-void _NPN_RegisterObjectOwner(NPP);
+// The ownership hierarchy is flat, and not a tree. Imagine the following
+// object creation:
+// PluginObject
+// |
+// +-- Creates -----> Object1
+// |
+// +-- Creates -----> Object2
+//
+// PluginObject will be the "owner" for both Object1 and Object2.
-// Unregisters the supplied plugin NPP identifier as an object owner. If there
-// are objects owned by this identifier then they are released.
-void _NPN_UnregisterObjectOwner(NPP);
+// Register an NPObject with the runtime. If the owner is NULL, the
+// object is treated as an owning object. If owner is not NULL,
+// this object will be registered as owned by owner's top-level owner.
+void _NPN_RegisterObject(NPObject*, NPObject* owner);
-NPP _NPN_GetObjectOwner(NPObject*);
+// Unregister an NPObject with the runtime. If obj is an owning
+// object, this call will also unregister all of the owned objects.
+void _NPN_UnregisterObject(NPObject*);
// Check to see if an object is registered with the runtime.
// Return true if registered, false otherwise.