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.