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

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: Rebased 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
« no previous file with comments | « Source/bindings/v8/CustomElementHelpers.h ('k') | Source/bindings/v8/V8AdaptorFunction.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/bindings/v8/CustomElementHelpers.cpp
diff --git a/Source/bindings/v8/CustomElementHelpers.cpp b/Source/bindings/v8/CustomElementHelpers.cpp
index 2a6087d73491f88c53eabdcc4d2fb9c44e62b0c3..9d4b40d158f0aa79157cd9d42720637419876092 100644
--- a/Source/bindings/v8/CustomElementHelpers.cpp
+++ b/Source/bindings/v8/CustomElementHelpers.cpp
@@ -34,15 +34,19 @@
#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 "bindings/v8/ScriptState.h"
#include "bindings/v8/UnsafePersistent.h"
+#include "bindings/v8/V8HiddenPropertyName.h"
#include "bindings/v8/V8PerContextData.h"
#include "core/dom/CustomElementRegistry.h"
+#include "core/dom/Element.h"
+#include "core/dom/ExceptionCode.h"
#include "core/dom/Node.h"
#include "core/html/HTMLElement.h"
#include "core/html/HTMLUnknownElement.h"
@@ -138,27 +142,79 @@ v8::Handle<v8::Object> CustomElementHelpers::createUpgradeCandidateWrapper(PassR
}
}
-bool CustomElementHelpers::initializeConstructorWrapper(CustomElementConstructor* constructor, const ScriptValue& prototype, ScriptState* state)
+static void constructCustomElement(const v8::FunctionCallbackInfo<v8::Value>& args)
{
- 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(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());
+ 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->isolate();
+
+ v8::HandleScope handleScope;
+ 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();
+ }
+ if (constructor.IsEmpty()) {
+ state->setException(v8::Local<v8::Value>::New(setDOMException(INVALID_STATE_ERR, isolate)));
+ return ScriptValue();
+ }
+
+ v8::Handle<v8::String> v8Name = v8String(name, isolate);
+ v8::Handle<v8::Value> v8Type = v8StringOrNull(type, isolate);
+
+ constructor->SetName(v8Type->IsNull() ? v8Name : v8::Handle<v8::String>::Cast(v8Type));
+
+ V8HiddenPropertyName::setNamedHiddenReference(constructor, "document", toV8(document, state->context()->Global(), isolate));
+ V8HiddenPropertyName::setNamedHiddenReference(constructor, "namespaceURI", v8String(namespaceURI, isolate));
+ V8HiddenPropertyName::setNamedHiddenReference(constructor, "name", v8Name);
+ V8HiddenPropertyName::setNamedHiddenReference(constructor, "type", 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)
« no previous file with comments | « Source/bindings/v8/CustomElementHelpers.h ('k') | Source/bindings/v8/V8AdaptorFunction.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698