[Custom Elements][V8] Custom Element doesn't need its own WrapperTypeInfo
authormorrita@google.com <morrita@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Mar 2013 02:52:34 +0000 (02:52 +0000)
committermorrita@google.com <morrita@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Mar 2013 02:52:34 +0000 (02:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=111411

Reviewed by Kentaro Hara.

No new tests. No observable change yet.

This is a preparation for Bug 110436, where WebKit is going to
allow any HTML element to be a superclass of custom elements.

This change eliminates WrapperTypeInfo for custom element. Instead
of that, the wrapper of a custom element picks WrapperTypeInfo
from most descendant built-in HTML element. For example, think about
following hierarchy:

- ... <- HTMLElement <- HTMLDivElememnt <- ExistingCustomElement <- NewCustomElement

In this case, both ExistingCustomElement and NewCustomElement has
HTMLDivElememnt's type info. This is because HTMLDivElememnt is
the most descendant (or "the nearest") built-in HTML
element. (HTMLElement isn't the most descendant.
ExistingCustomElement isn't a built-in.)

Using such WrapperTypeInfos, created custom element wrappers can
get appropriate set of method and properties regardless of its
super-elements.

This change tells the prototype object of each built-in object
which WrapperTypeInfo the native backing wants:
HTMLDivElememnt.prototype knows V8HTMLDivElement::info for
example. The pointer to the type info is stored into an internal
field. On wrapper construction, createWrapper() walks up the
prototype chain and pick the first one.

* bindings/v8/V8DOMConfiguration.cpp:
(WebCore::V8DOMConfiguration::configureTemplate):
* bindings/v8/V8HTMLCustomElement.cpp:
(WebCore::findWrapperTypeOf):
(WebCore::V8HTMLCustomElement::createWrapper):
* bindings/v8/V8HTMLCustomElement.h:
* bindings/v8/V8PerContextData.cpp:
(WebCore::V8PerContextData::constructorForTypeSlowCase):
* bindings/v8/WrapperTypeInfo.h:
(WebCore):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@144865 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/bindings/v8/V8DOMConfiguration.cpp
Source/WebCore/bindings/v8/V8HTMLCustomElement.cpp
Source/WebCore/bindings/v8/V8HTMLCustomElement.h
Source/WebCore/bindings/v8/V8PerContextData.cpp
Source/WebCore/bindings/v8/WrapperTypeInfo.h

index cdf79f6..0d8bbd3 100644 (file)
@@ -1,3 +1,50 @@
+2013-03-05  Hajime Morrita  <morrita@google.com>
+
+        [Custom Elements][V8] Custom Element doesn't need its own WrapperTypeInfo
+        https://bugs.webkit.org/show_bug.cgi?id=111411
+
+        Reviewed by Kentaro Hara.
+
+        No new tests. No observable change yet.
+
+        This is a preparation for Bug 110436, where WebKit is going to
+        allow any HTML element to be a superclass of custom elements.
+
+        This change eliminates WrapperTypeInfo for custom element. Instead
+        of that, the wrapper of a custom element picks WrapperTypeInfo
+        from most descendant built-in HTML element. For example, think about
+        following hierarchy:
+
+        - ... <- HTMLElement <- HTMLDivElememnt <- ExistingCustomElement <- NewCustomElement
+
+        In this case, both ExistingCustomElement and NewCustomElement has
+        HTMLDivElememnt's type info. This is because HTMLDivElememnt is
+        the most descendant (or "the nearest") built-in HTML
+        element. (HTMLElement isn't the most descendant.
+        ExistingCustomElement isn't a built-in.)
+
+        Using such WrapperTypeInfos, created custom element wrappers can
+        get appropriate set of method and properties regardless of its
+        super-elements.
+
+        This change tells the prototype object of each built-in object
+        which WrapperTypeInfo the native backing wants:
+        HTMLDivElememnt.prototype knows V8HTMLDivElement::info for
+        example. The pointer to the type info is stored into an internal
+        field. On wrapper construction, createWrapper() walks up the
+        prototype chain and pick the first one.
+
+        * bindings/v8/V8DOMConfiguration.cpp:
+        (WebCore::V8DOMConfiguration::configureTemplate):
+        * bindings/v8/V8HTMLCustomElement.cpp:
+        (WebCore::findWrapperTypeOf):
+        (WebCore::V8HTMLCustomElement::createWrapper):
+        * bindings/v8/V8HTMLCustomElement.h:
+        * bindings/v8/V8PerContextData.cpp:
+        (WebCore::V8PerContextData::constructorForTypeSlowCase):
+        * bindings/v8/WrapperTypeInfo.h:
+        (WebCore):
+
 2013-03-05  Aaron Colwell  <acolwell@chromium.org>
 
         Heap-use-after-free in WebCore::HTMLMediaElement::~HTMLMediaElement
index b4f1a28..5fe7bcf 100644 (file)
@@ -33,8 +33,6 @@
 
 namespace WebCore {
 
-const int prototypeInternalFieldcount = 1;
-
 void V8DOMConfiguration::batchConfigureAttributes(v8::Handle<v8::ObjectTemplate> instance, v8::Handle<v8::ObjectTemplate> prototype, const BatchedAttribute* attributes, size_t attributeCount, v8::Isolate* isolate)
 {
     for (size_t i = 0; i < attributeCount; ++i)
@@ -68,7 +66,7 @@ v8::Local<v8::Signature> V8DOMConfiguration::configureTemplate(v8::Persistent<v8
         // This is needed since bug 110436 asks WebKit to tell native-initiated prototypes from pure-JS ones.
         // This doesn't mark kinds "root" classes like Node, where setting this changes prototype chain structure.
         v8::Local<v8::ObjectTemplate> prototype = functionDescriptor->PrototypeTemplate();
-        prototype->SetInternalFieldCount(prototypeInternalFieldcount);
+        prototype->SetInternalFieldCount(v8PrototypeInternalFieldcount);
     }
 
     if (attributeCount)
index f47f359..d014b0f 100644 (file)
 #include "CustomElementRegistry.h"
 #include "HTMLElement.h"
 #include "V8CustomElementConstructor.h"
-#include "V8HTMLSpanElement.h"
+#include "V8HTMLUnknownElement.h"
 
 namespace WebCore {
 
-// FIXME: Each custom elements should have its own GetTemplate method so that it can be derived from different super element.
-WrapperTypeInfo V8HTMLCustomElement::info = { &V8HTMLElement::GetTemplate, V8HTMLElement::derefObject, 0, V8HTMLElement::toEventTarget, 0, 0, &V8HTMLElement::info, WrapperTypeObjectPrototype };
+static WrapperTypeInfo* findWrapperTypeOf(v8::Handle<v8::Value> chain)
+{
+    while (!chain.IsEmpty() && chain->IsObject()) {
+        v8::Handle<v8::Object> chainObject = v8::Handle<v8::Object>::Cast(chain);
+        if (v8PrototypeInternalFieldcount == chainObject->InternalFieldCount())
+            return reinterpret_cast<WrapperTypeInfo*>(chainObject->GetAlignedPointerFromInternalField(v8PrototypeTypeIndex));
+        chain = chainObject->GetPrototype();
+    }
+
+    return 0;
+}
 
 v8::Handle<v8::Object> V8HTMLCustomElement::createWrapper(PassRefPtr<HTMLElement> impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
 {
@@ -57,22 +66,31 @@ v8::Handle<v8::Object> V8HTMLCustomElement::createWrapper(PassRefPtr<HTMLElement
         return v8::Handle<v8::Object>();
     }
 
-    v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, &info, impl.get(), isolate);
-    if (wrapper.IsEmpty())
-        return wrapper;
-
     // 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(creationContext->CreationContext())) {
-        v8::Handle<v8::Value> wrapperValue = WebCore::toV8(constructor.get(), creationContext, isolate);
-        if (wrapperValue.IsEmpty() || !wrapperValue->IsObject())
-            return v8::Handle<v8::Object>();
-        v8::Handle<v8::Object> constructorWapper = v8::Handle<v8::Object>::Cast(wrapperValue);
-        wrapper->SetPrototype(constructorWapper->Get(v8String("prototype", isolate)));
+    if (!CustomElementHelpers::isFeatureAllowed(creationContext->CreationContext())) {
+        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;
     }
 
-    V8DOMWrapper::associateObjectWithWrapper(impl, &info, wrapper, isolate, WrapperConfiguration::Dependent);
+    v8::Handle<v8::Value> constructorValue = WebCore::toV8(constructor.get(), creationContext, isolate);
+    if (constructorValue.IsEmpty() || !constructorValue->IsObject())
+        return v8::Handle<v8::Object>();
+    v8::Handle<v8::Object> constructorWapper = v8::Handle<v8::Object>::Cast(constructorValue);
+    v8::Handle<v8::Object> prototype = v8::Handle<v8::Object>::Cast(constructorWapper->Get(v8::String::NewSymbol("prototype")));
+    WrapperTypeInfo* typeInfo = findWrapperTypeOf(prototype);
+    if (!typeInfo)
+        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;
 }
 
index f380a01..d68b05b 100644 (file)
@@ -45,7 +45,6 @@ class HTMLElement;
 
 class V8HTMLCustomElement {
 public:
-    static WrapperTypeInfo info;
     static v8::Handle<v8::Value> toV8(HTMLElement*, v8::Handle<v8::Object> creationContext = v8::Handle<v8::Object>(), v8::Isolate* = 0);
     static v8::Handle<v8::Object> wrap(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*);
 
index 86eeb12..ee8a0e6 100644 (file)
@@ -126,6 +126,9 @@ v8::Local<v8::Function> V8PerContextData::constructorForTypeSlowCase(WrapperType
     v8::Local<v8::Value> prototypeValue = function->Get(v8::String::NewSymbol("prototype"));
     if (!prototypeValue.IsEmpty() && prototypeValue->IsObject()) {
         v8::Local<v8::Object> prototypeObject = v8::Local<v8::Object>::Cast(prototypeValue);
+        if (prototypeObject->InternalFieldCount() == v8PrototypeInternalFieldcount
+            && type->wrapperTypePrototype == WrapperTypeObjectPrototype)
+            prototypeObject->SetAlignedPointerInInternalField(v8PrototypeTypeIndex, type);
         type->installPerContextPrototypeProperties(prototypeObject, m_context->GetIsolate());
         if (type->wrapperTypePrototype == WrapperTypeErrorPrototype)
             prototypeObject->SetPrototype(m_errorPrototype.get());
index dc2a5ee..456e002 100644 (file)
@@ -43,6 +43,8 @@ namespace WebCore {
     static const int v8DOMWrapperTypeIndex = 0;
     static const int v8DOMWrapperObjectIndex = 1;
     static const int v8DefaultWrapperInternalFieldCount = 2;
+    static const int v8PrototypeTypeIndex = 0;
+    static const int v8PrototypeInternalFieldcount = 1;
 
     static const uint16_t v8DOMNodeClassId = 1;
     static const uint16_t v8DOMObjectClassId = 2;