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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 16 matching lines...) Expand all
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 32
33 #include "bindings/v8/CustomElementHelpers.h" 33 #include "bindings/v8/CustomElementHelpers.h"
34 34
35 #include "HTMLNames.h" 35 #include "HTMLNames.h"
36 #include "SVGNames.h" 36 #include "SVGNames.h"
37 #include "V8CustomElementConstructor.h" 37 #include "V8Document.h"
38 #include "V8HTMLElementWrapperFactory.h" 38 #include "V8HTMLElementWrapperFactory.h"
39 #include "V8SVGElementWrapperFactory.h" 39 #include "V8SVGElementWrapperFactory.h"
40 #include "bindings/v8/DOMDataStore.h" 40 #include "bindings/v8/DOMDataStore.h"
41 #include "bindings/v8/DOMWrapperWorld.h" 41 #include "bindings/v8/DOMWrapperWorld.h"
42 #include "bindings/v8/ScriptController.h" 42 #include "bindings/v8/ScriptController.h"
43 #include "core/dom/CustomElementRegistry.h" 43 #include "core/dom/CustomElementRegistry.h"
44 #include "core/dom/Element.h"
44 #include "core/dom/Node.h" 45 #include "core/dom/Node.h"
45 #include "core/html/HTMLElement.h" 46 #include "core/html/HTMLElement.h"
46 #include "core/html/HTMLUnknownElement.h" 47 #include "core/html/HTMLUnknownElement.h"
47 #include "core/svg/SVGElement.h" 48 #include "core/svg/SVGElement.h"
48 49
49 namespace WebCore { 50 namespace WebCore {
50 51
51 v8::Handle<v8::Object> CustomElementHelpers::createWrapper(PassRefPtr<Element> i mpl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate, const CreateW rapperFunction& createTypeExtensionUpgradeCandidateWrapper) 52 v8::Handle<v8::Object> CustomElementHelpers::createWrapper(PassRefPtr<Element> i mpl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate, const CreateW rapperFunction& createTypeExtensionUpgradeCandidateWrapper)
52 { 53 {
53 ASSERT(impl); 54 ASSERT(impl);
54 55
55 // The constructor and registered lifecycle callbacks should be visible only from main world. 56 // The constructor and registered lifecycle callbacks should be visible only from main world.
56 // FIXME: This shouldn't be needed once each custom element has its own Func tionTemplate
57 // https://bugs.webkit.org/show_bug.cgi?id=108138
58 57
59 // FIXME: creationContext.IsEmpty() should never happen. Remove 58 // FIXME: creationContext.IsEmpty() should never happen. Remove
60 // this when callers (like InspectorController::inspect) are fixed 59 // this when callers (like InspectorController::inspect) are fixed
61 // to never pass an empty creation context. 60 // to never pass an empty creation context.
62 if (!CustomElementHelpers::isFeatureAllowed(creationContext.IsEmpty() ? v8:: Context::GetCurrent() : creationContext->CreationContext())) { 61 if (!CustomElementHelpers::isFeatureAllowed(creationContext.IsEmpty() ? v8:: Context::GetCurrent() : creationContext->CreationContext())) {
63 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationCon text, &V8HTMLElement::info, impl.get(), isolate); 62 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationCon text, &V8HTMLElement::info, impl.get(), isolate);
64 if (!wrapper.IsEmpty()) 63 if (!wrapper.IsEmpty())
65 V8DOMWrapper::associateObjectWithWrapper(impl, &V8HTMLElement::info, wrapper, isolate, WrapperConfiguration::Dependent); 64 V8DOMWrapper::associateObjectWithWrapper(impl, &V8HTMLElement::info, wrapper, isolate, WrapperConfiguration::Dependent);
66 return wrapper; 65 return wrapper;
67 } 66 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 else { 113 else {
115 ASSERT(0); 114 ASSERT(0);
116 return v8::Handle<v8::Object>(); 115 return v8::Handle<v8::Object>();
117 } 116 }
118 } else { 117 } else {
119 // It's a type extension 118 // It's a type extension
120 return createTypeExtensionUpgradeCandidateWrapper.invoke(element.get(), creationContext, isolate); 119 return createTypeExtensionUpgradeCandidateWrapper.invoke(element.get(), creationContext, isolate);
121 } 120 }
122 } 121 }
123 122
124 bool CustomElementHelpers::initializeConstructorWrapper(CustomElementConstructor * constructor, const ScriptValue& prototype, ScriptState* state) 123 void constructCustomElement(const v8::FunctionCallbackInfo<v8::Value>& args)
Hajime Morrita 2013/06/10 04:32:22 Nit: can be static.
125 { 124 {
126 ASSERT(isFeatureAllowed(state)); 125 v8::Isolate* isolate = args.GetIsolate();
127 ASSERT(!prototype.v8Value().IsEmpty() && prototype.v8Value()->IsObject());
128 v8::Handle<v8::Value> wrapperValue = toV8(constructor, state->context()->Glo bal(), state->context()->GetIsolate());
129 if (wrapperValue.IsEmpty() || !wrapperValue->IsObject())
130 return false;
131 v8::Handle<v8::Function> wrapper = v8::Handle<v8::Function>::Cast(wrapperVal ue);
132 // - Object::ForceSet() nor Object::SetAccessor Doesn't work against the "pr ototype" property of function objects.
133 // - Set()-ing here is safe because
134 // - Hooking Object.prototype's defineProperty() with "prototype" or "cons tructor" also doesn't affect on these properties of function objects and
135 // - Using Set() is okay becaues each function has "prototype" property fr om start and Objects.prototype cannot intercept the property access.
136 v8::Handle<v8::String> prototypeKey = v8String("prototype", state->context() ->GetIsolate());
137 ASSERT(wrapper->HasOwnProperty(prototypeKey));
138 wrapper->Set(prototypeKey, prototype.v8Value(), v8::ReadOnly);
139 126
140 v8::Handle<v8::String> constructorKey = v8String("constructor", state->conte xt()->GetIsolate()); 127 if (!args.IsConstructCall()) {
141 v8::Handle<v8::Object> prototypeObject = v8::Handle<v8::Object>::Cast(protot ype.v8Value()); 128 throwTypeError("DOM object constructor cannot be called as a function.", isolate);
142 ASSERT(!prototypeObject->HasOwnProperty(constructorKey)); 129 return;
143 prototypeObject->ForceSet(constructorKey, wrapper, v8::ReadOnly); 130 }
144 return true; 131
132 if (args.Length() > 0) {
133 throwTypeError(0, isolate);
134 return;
135 }
136
137 Document* document = V8Document::toNative(v8::Handle<v8::Object>::Cast(args. Callee()->GetHiddenValue(v8String("document", isolate))));
138 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, args. Callee()->GetHiddenValue(v8String("namespaceURI", isolate)));
139 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, args.Callee() ->GetHiddenValue(v8String("name", isolate)));
140 v8::Handle<v8::Value> maybeType = args.Callee()->GetHiddenValue(v8String("ty pe", isolate));
141 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, maybeType);
142
143 ExceptionCode ec = 0;
144 CustomElementRegistry::CallbackDeliveryScope deliveryScope;
145 RefPtr<Element> element = document->createElementNS(namespaceURI, name, mayb eType->IsNull() ? nullAtom : type, ec);
146 if (ec) {
147 setDOMException(ec, isolate);
148 return;
149 }
150 v8SetReturnValue(args, toV8Fast(element.release(), args, document));
151 }
152
153 ScriptValue CustomElementHelpers::createConstructor(ScriptState* state, const Sc riptValue& prototypeValue, Document* document, const AtomicString& namespaceURI, const AtomicString& name, const AtomicString& type)
154 {
155 v8::Isolate* isolate = state->context()->GetIsolate();
156
157 v8::TryCatch tryCatch;
158 v8::Local<v8::FunctionTemplate> constructorTemplate = v8::FunctionTemplate:: New();
159 constructorTemplate->SetCallHandler(constructCustomElement);
160 v8::Handle<v8::Function> constructor = constructorTemplate->GetFunction();
161 if (tryCatch.HasCaught()) {
162 state->setException(tryCatch.Exception());
163 return ScriptValue();
164 }
165
166 v8::Handle<v8::String> v8Name = v8String(name, isolate);
167 v8::Handle<v8::Value> v8Type;
168
169 if (type.isNull()) {
170 v8Type = v8::Null(isolate);
171 constructor->SetName(v8Name);
172 } else {
173 v8::Handle<v8::String> v8TypeString = v8String(type, isolate);
174 v8Type = v8TypeString;
175 constructor->SetName(v8TypeString);
176 }
177
178 constructor->SetHiddenValue(v8String("document", isolate), toV8(document, st ate->context()->Global(), isolate));
179 constructor->SetHiddenValue(v8String("namespaceURI", isolate), v8String(name spaceURI, isolate));
180 constructor->SetHiddenValue(v8String("name", isolate), v8Name);
181 constructor->SetHiddenValue(v8String("type", isolate), v8Type);
182
183 // Neither Object::ForceSet nor Object::SetAccessor can set the
184 // "prototype" property of function objects, so we use Set()
185 // instead. This is safe because each function has "prototype"
186 // property from birth so the Function, etc. prototypes will not
187 // intercept the property access.
188 v8::Handle<v8::Object> prototype = v8::Handle<v8::Object>::Cast(prototypeVal ue.v8Value());
189 v8::Handle<v8::String> prototypeKey = v8String("prototype", isolate);
190 ASSERT(constructor->HasOwnProperty(prototypeKey));
191 constructor->Set(prototypeKey, prototype, v8::ReadOnly);
192
193 prototype->ForceSet(v8String("constructor", isolate), constructor, v8::ReadO nly);
194
195 ASSERT(!tryCatch.HasCaught());
196
197 return ScriptValue(constructor);
145 } 198 }
146 199
147 static bool hasValidPrototypeChainFor(v8::Handle<v8::Object> prototypeObject, Wr apperTypeInfo* typeInfo, v8::Handle<v8::Context> context) 200 static bool hasValidPrototypeChainFor(v8::Handle<v8::Object> prototypeObject, Wr apperTypeInfo* typeInfo, v8::Handle<v8::Context> context)
148 { 201 {
149 // document.register() sets the constructor property, so the prototype shoul dn't have one. 202 // document.register() sets the constructor property, so the prototype shoul dn't have one.
150 if (prototypeObject->HasOwnProperty(v8String("constructor", context->GetIsol ate()))) 203 if (prototypeObject->HasOwnProperty(v8String("constructor", context->GetIsol ate())))
151 return false; 204 return false;
152 205
153 v8::Handle<v8::Object> elementConstructor = v8::Handle<v8::Object>::Cast(V8P erContextData::from(context)->constructorForType(typeInfo)); 206 v8::Handle<v8::Object> elementConstructor = v8::Handle<v8::Object>::Cast(V8P erContextData::from(context)->constructorForType(typeInfo));
154 if (elementConstructor.IsEmpty()) 207 if (elementConstructor.IsEmpty())
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 return; 343 return;
291 v8::Context::Scope scope(context); 344 v8::Context::Scope scope(context);
292 345
293 for (size_t i = 0; i < invocations.size(); ++i) { 346 for (size_t i = 0; i < invocations.size(); ++i) {
294 ASSERT(executionContext == invocations[i].element()->document()); 347 ASSERT(executionContext == invocations[i].element()->document());
295 invokeReadyCallbackIfNeeded(invocations[i].element(), context); 348 invokeReadyCallbackIfNeeded(invocations[i].element(), context);
296 } 349 }
297 } 350 }
298 351
299 } // namespace WebCore 352 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698