Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(376)

Unified Diff: Source/bindings/v8/CustomElementHelpers.cpp

Issue 16708002: Simplify Custom Element constructors to be functions, not wrappers (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix callback functions as parameters Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/bindings/v8/CustomElementHelpers.cpp
diff --git a/Source/bindings/v8/CustomElementHelpers.cpp b/Source/bindings/v8/CustomElementHelpers.cpp
index a55d0628ca941466e4f233a246728eda2021bbd8..d1e9adf53ce67f199edcac19cc860e63b9da4f54 100644
--- a/Source/bindings/v8/CustomElementHelpers.cpp
+++ b/Source/bindings/v8/CustomElementHelpers.cpp
@@ -34,13 +34,14 @@
#include "HTMLNames.h"
#include "SVGNames.h"
-#include "V8CustomElementConstructor.h"
+#include "V8Document.h"
#include "V8HTMLElementWrapperFactory.h"
#include "V8SVGElementWrapperFactory.h"
#include "bindings/v8/DOMDataStore.h"
#include "bindings/v8/DOMWrapperWorld.h"
#include "bindings/v8/ScriptController.h"
#include "core/dom/CustomElementRegistry.h"
+#include "core/dom/Element.h"
#include "core/dom/Node.h"
#include "core/html/HTMLElement.h"
#include "core/html/HTMLUnknownElement.h"
@@ -53,8 +54,6 @@ v8::Handle<v8::Object> CustomElementHelpers::createWrapper(PassRefPtr<Element> i
ASSERT(impl);
// 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
// FIXME: creationContext.IsEmpty() should never happen. Remove
// this when callers (like InspectorController::inspect) are fixed
@@ -121,27 +120,81 @@ v8::Handle<v8::Object> CustomElementHelpers::createUpgradeCandidateWrapper(PassR
}
}
-bool CustomElementHelpers::initializeConstructorWrapper(CustomElementConstructor* constructor, const ScriptValue& prototype, ScriptState* state)
+void constructCustomElement(const v8::FunctionCallbackInfo<v8::Value>& args)
Hajime Morrita 2013/06/10 04:32:22 Nit: can be static.
{
- ASSERT(isFeatureAllowed(state));
- ASSERT(!prototype.v8Value().IsEmpty() && prototype.v8Value()->IsObject());
- v8::Handle<v8::Value> wrapperValue = toV8(constructor, state->context()->Global(), state->context()->GetIsolate());
- if (wrapperValue.IsEmpty() || !wrapperValue->IsObject())
- return false;
- v8::Handle<v8::Function> wrapper = v8::Handle<v8::Function>::Cast(wrapperValue);
- // - Object::ForceSet() nor Object::SetAccessor Doesn't work against the "prototype" property of function objects.
- // - Set()-ing here is safe because
- // - Hooking Object.prototype's defineProperty() with "prototype" or "constructor" also doesn't affect on these properties of function objects and
- // - Using Set() is okay becaues each function has "prototype" property from start and Objects.prototype cannot intercept the property access.
- v8::Handle<v8::String> prototypeKey = v8String("prototype", state->context()->GetIsolate());
- ASSERT(wrapper->HasOwnProperty(prototypeKey));
- wrapper->Set(prototypeKey, prototype.v8Value(), v8::ReadOnly);
-
- v8::Handle<v8::String> constructorKey = v8String("constructor", state->context()->GetIsolate());
- v8::Handle<v8::Object> prototypeObject = v8::Handle<v8::Object>::Cast(prototype.v8Value());
- ASSERT(!prototypeObject->HasOwnProperty(constructorKey));
- prototypeObject->ForceSet(constructorKey, wrapper, v8::ReadOnly);
- return true;
+ v8::Isolate* isolate = args.GetIsolate();
+
+ if (!args.IsConstructCall()) {
+ throwTypeError("DOM object constructor cannot be called as a function.", isolate);
+ return;
+ }
+
+ if (args.Length() > 0) {
+ throwTypeError(0, isolate);
+ return;
+ }
+
+ Document* document = V8Document::toNative(v8::Handle<v8::Object>::Cast(args.Callee()->GetHiddenValue(v8String("document", isolate))));
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, args.Callee()->GetHiddenValue(v8String("namespaceURI", isolate)));
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, args.Callee()->GetHiddenValue(v8String("name", isolate)));
+ v8::Handle<v8::Value> maybeType = args.Callee()->GetHiddenValue(v8String("type", isolate));
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, maybeType);
+
+ ExceptionCode ec = 0;
+ CustomElementRegistry::CallbackDeliveryScope deliveryScope;
+ RefPtr<Element> element = document->createElementNS(namespaceURI, name, maybeType->IsNull() ? nullAtom : type, ec);
+ if (ec) {
+ setDOMException(ec, isolate);
+ return;
+ }
+ v8SetReturnValue(args, toV8Fast(element.release(), args, document));
+}
+
+ScriptValue CustomElementHelpers::createConstructor(ScriptState* state, const ScriptValue& prototypeValue, Document* document, const AtomicString& namespaceURI, const AtomicString& name, const AtomicString& type)
+{
+ v8::Isolate* isolate = state->context()->GetIsolate();
+
+ v8::TryCatch tryCatch;
+ v8::Local<v8::FunctionTemplate> constructorTemplate = v8::FunctionTemplate::New();
+ constructorTemplate->SetCallHandler(constructCustomElement);
+ v8::Handle<v8::Function> constructor = constructorTemplate->GetFunction();
+ if (tryCatch.HasCaught()) {
+ state->setException(tryCatch.Exception());
+ return ScriptValue();
+ }
+
+ v8::Handle<v8::String> v8Name = v8String(name, isolate);
+ v8::Handle<v8::Value> v8Type;
+
+ if (type.isNull()) {
+ v8Type = v8::Null(isolate);
+ constructor->SetName(v8Name);
+ } else {
+ v8::Handle<v8::String> v8TypeString = v8String(type, isolate);
+ v8Type = v8TypeString;
+ constructor->SetName(v8TypeString);
+ }
+
+ constructor->SetHiddenValue(v8String("document", isolate), toV8(document, state->context()->Global(), isolate));
+ constructor->SetHiddenValue(v8String("namespaceURI", isolate), v8String(namespaceURI, isolate));
+ constructor->SetHiddenValue(v8String("name", isolate), v8Name);
+ constructor->SetHiddenValue(v8String("type", isolate), v8Type);
+
+ // Neither Object::ForceSet nor Object::SetAccessor can set the
+ // "prototype" property of function objects, so we use Set()
+ // instead. This is safe because each function has "prototype"
+ // property from birth so the Function, etc. prototypes will not
+ // intercept the property access.
+ v8::Handle<v8::Object> prototype = v8::Handle<v8::Object>::Cast(prototypeValue.v8Value());
+ v8::Handle<v8::String> prototypeKey = v8String("prototype", isolate);
+ ASSERT(constructor->HasOwnProperty(prototypeKey));
+ constructor->Set(prototypeKey, prototype, v8::ReadOnly);
+
+ prototype->ForceSet(v8String("constructor", isolate), constructor, v8::ReadOnly);
+
+ ASSERT(!tryCatch.HasCaught());
+
+ return ScriptValue(constructor);
}
static bool hasValidPrototypeChainFor(v8::Handle<v8::Object> prototypeObject, WrapperTypeInfo* typeInfo, v8::Handle<v8::Context> context)

Powered by Google App Engine
This is Rietveld 408576698