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

Side by Side Diff: Source/bindings/v8/CustomElementConstructorBuilder.cpp

Issue 351423002: Moved files under Source/bindings/v8 to Source/bindings/core/v8. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 5 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
(Empty)
1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
29 */
30
31 #include "config.h"
32 #include "bindings/v8/CustomElementConstructorBuilder.h"
33
34 #include "bindings/core/v8/V8Document.h"
35 #include "bindings/v8/CustomElementBinding.h"
36 #include "bindings/v8/DOMWrapperWorld.h"
37 #include "bindings/v8/Dictionary.h"
38 #include "bindings/v8/ExceptionState.h"
39 #include "bindings/v8/V8Binding.h"
40 #include "bindings/v8/V8HiddenValue.h"
41 #include "bindings/v8/V8PerContextData.h"
42 #include "core/HTMLNames.h"
43 #include "core/SVGNames.h"
44 #include "core/V8HTMLElementWrapperFactory.h" // FIXME: should be bindings/core/ v8
45 #include "core/V8SVGElementWrapperFactory.h" // FIXME: should be bindings/core/v 8
46 #include "core/dom/Document.h"
47 #include "core/dom/custom/CustomElementCallbackDispatcher.h"
48 #include "core/dom/custom/CustomElementDefinition.h"
49 #include "core/dom/custom/CustomElementDescriptor.h"
50 #include "core/dom/custom/CustomElementException.h"
51 #include "wtf/Assertions.h"
52
53 namespace WebCore {
54
55 static void constructCustomElement(const v8::FunctionCallbackInfo<v8::Value>&);
56
57 CustomElementConstructorBuilder::CustomElementConstructorBuilder(ScriptState* sc riptState, const Dictionary* options)
58 : m_scriptState(scriptState)
59 , m_options(options)
60 , m_wrapperType(0)
61 {
62 ASSERT(m_scriptState->context() == m_scriptState->isolate()->GetCurrentConte xt());
63 }
64
65 bool CustomElementConstructorBuilder::isFeatureAllowed() const
66 {
67 return m_scriptState->world().isMainWorld();
68 }
69
70 bool CustomElementConstructorBuilder::validateOptions(const AtomicString& type, QualifiedName& tagName, ExceptionState& exceptionState)
71 {
72 ASSERT(m_prototype.IsEmpty());
73
74 v8::TryCatch tryCatch;
75
76 ScriptValue prototypeScriptValue;
77 if (m_options->get("prototype", prototypeScriptValue) && !prototypeScriptVal ue.isNull()) {
78 ASSERT(!tryCatch.HasCaught());
79 if (!prototypeScriptValue.isObject()) {
80 CustomElementException::throwException(CustomElementException::Proto typeNotAnObject, type, exceptionState);
81 tryCatch.ReThrow();
82 return false;
83 }
84 m_prototype = prototypeScriptValue.v8Value().As<v8::Object>();
85 } else if (!tryCatch.HasCaught()) {
86 m_prototype = v8::Object::New(m_scriptState->isolate());
87 v8::Local<v8::Object> basePrototype = m_scriptState->perContextData()->p rototypeForType(&V8HTMLElement::wrapperTypeInfo);
88 if (!basePrototype.IsEmpty())
89 m_prototype->SetPrototype(basePrototype);
90 }
91
92 if (tryCatch.HasCaught()) {
93 tryCatch.ReThrow();
94 return false;
95 }
96
97 AtomicString extends;
98 bool extendsProvidedAndNonNull = m_options->get("extends", extends);
99
100 if (tryCatch.HasCaught()) {
101 tryCatch.ReThrow();
102 return false;
103 }
104
105 if (!m_scriptState->perContextData()) {
106 // FIXME: This should generate an InvalidContext exception at a later po int.
107 CustomElementException::throwException(CustomElementException::ContextDe stroyedCheckingPrototype, type, exceptionState);
108 tryCatch.ReThrow();
109 return false;
110 }
111
112 AtomicString namespaceURI = HTMLNames::xhtmlNamespaceURI;
113 if (hasValidPrototypeChainFor(&V8SVGElement::wrapperTypeInfo))
114 namespaceURI = SVGNames::svgNamespaceURI;
115
116 ASSERT(!tryCatch.HasCaught());
117
118 AtomicString localName;
119
120 if (extendsProvidedAndNonNull) {
121 localName = extends.lower();
122
123 if (!Document::isValidName(localName)) {
124 CustomElementException::throwException(CustomElementException::Exten dsIsInvalidName, type, exceptionState);
125 tryCatch.ReThrow();
126 return false;
127 }
128 if (CustomElement::isValidName(localName)) {
129 CustomElementException::throwException(CustomElementException::Exten dsIsCustomElementName, type, exceptionState);
130 tryCatch.ReThrow();
131 return false;
132 }
133 } else {
134 if (namespaceURI == SVGNames::svgNamespaceURI) {
135 CustomElementException::throwException(CustomElementException::Exten dsIsInvalidName, type, exceptionState);
136 tryCatch.ReThrow();
137 return false;
138 }
139 localName = type;
140 }
141
142 if (!extendsProvidedAndNonNull)
143 m_wrapperType = &V8HTMLElement::wrapperTypeInfo;
144 else if (namespaceURI == HTMLNames::xhtmlNamespaceURI)
145 m_wrapperType = findWrapperTypeForHTMLTagName(localName);
146 else
147 m_wrapperType = findWrapperTypeForSVGTagName(localName);
148
149 ASSERT(!tryCatch.HasCaught());
150 ASSERT(m_wrapperType);
151 tagName = QualifiedName(nullAtom, localName, namespaceURI);
152 return m_wrapperType;
153 }
154
155 PassRefPtr<CustomElementLifecycleCallbacks> CustomElementConstructorBuilder::cre ateCallbacks()
156 {
157 ASSERT(!m_prototype.IsEmpty());
158
159 v8::TryCatch exceptionCatcher;
160 exceptionCatcher.SetVerbose(true);
161
162 v8::Isolate* isolate = m_scriptState->isolate();
163 v8::Handle<v8::Function> created = retrieveCallback(isolate, "createdCallbac k");
164 v8::Handle<v8::Function> attached = retrieveCallback(isolate, "attachedCallb ack");
165 v8::Handle<v8::Function> detached = retrieveCallback(isolate, "detachedCallb ack");
166 v8::Handle<v8::Function> attributeChanged = retrieveCallback(isolate, "attri buteChangedCallback");
167
168 m_callbacks = V8CustomElementLifecycleCallbacks::create(m_scriptState.get(), m_prototype, created, attached, detached, attributeChanged);
169 return m_callbacks.get();
170 }
171
172 v8::Handle<v8::Function> CustomElementConstructorBuilder::retrieveCallback(v8::I solate* isolate, const char* name)
173 {
174 v8::Handle<v8::Value> value = m_prototype->Get(v8String(isolate, name));
175 if (value.IsEmpty() || !value->IsFunction())
176 return v8::Handle<v8::Function>();
177 return value.As<v8::Function>();
178 }
179
180 bool CustomElementConstructorBuilder::createConstructor(Document* document, Cust omElementDefinition* definition, ExceptionState& exceptionState)
181 {
182 ASSERT(!m_prototype.IsEmpty());
183 ASSERT(m_constructor.IsEmpty());
184 ASSERT(document);
185
186 v8::Isolate* isolate = m_scriptState->isolate();
187
188 if (!prototypeIsValid(definition->descriptor().type(), exceptionState))
189 return false;
190
191 v8::Local<v8::FunctionTemplate> constructorTemplate = v8::FunctionTemplate:: New(isolate);
192 constructorTemplate->SetCallHandler(constructCustomElement);
193 m_constructor = constructorTemplate->GetFunction();
194 if (m_constructor.IsEmpty()) {
195 CustomElementException::throwException(CustomElementException::ContextDe stroyedRegisteringDefinition, definition->descriptor().type(), exceptionState);
196 return false;
197 }
198
199 const CustomElementDescriptor& descriptor = definition->descriptor();
200
201 v8::Handle<v8::String> v8TagName = v8String(isolate, descriptor.localName()) ;
202 v8::Handle<v8::Value> v8Type;
203 if (descriptor.isTypeExtension())
204 v8Type = v8String(isolate, descriptor.type());
205 else
206 v8Type = v8::Null(isolate);
207
208 m_constructor->SetName(v8Type->IsNull() ? v8TagName : v8Type.As<v8::String>( ));
209
210 V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customE lementDocument(isolate), toV8(document, m_scriptState->context()->Global(), isol ate));
211 V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customE lementNamespaceURI(isolate), v8String(isolate, descriptor.namespaceURI()));
212 V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customE lementTagName(isolate), v8TagName);
213 V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customE lementType(isolate), v8Type);
214
215 v8::Handle<v8::String> prototypeKey = v8String(isolate, "prototype");
216 ASSERT(m_constructor->HasOwnProperty(prototypeKey));
217 // This sets the property *value*; calling Set is safe because
218 // "prototype" is a non-configurable data property so there can be
219 // no side effects.
220 m_constructor->Set(prototypeKey, m_prototype);
221 // This *configures* the property. ForceSet of a function's
222 // "prototype" does not affect the value, but can reconfigure the
223 // property.
224 m_constructor->ForceSet(prototypeKey, m_prototype, v8::PropertyAttribute(v8: :ReadOnly | v8::DontEnum | v8::DontDelete));
225
226 V8HiddenValue::setHiddenValue(isolate, m_prototype, V8HiddenValue::customEle mentIsInterfacePrototypeObject(isolate), v8::True(isolate));
227 m_prototype->ForceSet(v8String(isolate, "constructor"), m_constructor, v8::D ontEnum);
228
229 return true;
230 }
231
232 bool CustomElementConstructorBuilder::prototypeIsValid(const AtomicString& type, ExceptionState& exceptionState) const
233 {
234 if (m_prototype->InternalFieldCount() || !V8HiddenValue::getHiddenValue(m_sc riptState->isolate(), m_prototype, V8HiddenValue::customElementIsInterfaceProtot ypeObject(m_scriptState->isolate())).IsEmpty()) {
235 CustomElementException::throwException(CustomElementException::Prototype InUse, type, exceptionState);
236 return false;
237 }
238
239 if (m_prototype->GetPropertyAttributes(v8String(m_scriptState->isolate(), "c onstructor")) & v8::DontDelete) {
240 CustomElementException::throwException(CustomElementException::Construct orPropertyNotConfigurable, type, exceptionState);
241 return false;
242 }
243
244 return true;
245 }
246
247 bool CustomElementConstructorBuilder::didRegisterDefinition(CustomElementDefinit ion* definition) const
248 {
249 ASSERT(!m_constructor.IsEmpty());
250
251 return m_callbacks->setBinding(definition, CustomElementBinding::create(m_sc riptState->isolate(), m_prototype, m_wrapperType));
252 }
253
254 ScriptValue CustomElementConstructorBuilder::bindingsReturnValue() const
255 {
256 return ScriptValue(m_scriptState.get(), m_constructor);
257 }
258
259 bool CustomElementConstructorBuilder::hasValidPrototypeChainFor(const WrapperTyp eInfo* type) const
260 {
261 v8::Handle<v8::Object> elementPrototype = m_scriptState->perContextData()->p rototypeForType(type);
262 if (elementPrototype.IsEmpty())
263 return false;
264
265 v8::Handle<v8::Value> chain = m_prototype;
266 while (!chain.IsEmpty() && chain->IsObject()) {
267 if (chain == elementPrototype)
268 return true;
269 chain = chain.As<v8::Object>()->GetPrototype();
270 }
271
272 return false;
273 }
274
275 static void constructCustomElement(const v8::FunctionCallbackInfo<v8::Value>& in fo)
276 {
277 v8::Isolate* isolate = info.GetIsolate();
278
279 if (!info.IsConstructCall()) {
280 throwTypeError("DOM object constructor cannot be called as a function.", isolate);
281 return;
282 }
283
284 if (info.Length() > 0) {
285 throwTypeError("This constructor should be called without arguments.", i solate);
286 return;
287 }
288
289 Document* document = V8Document::toNative(V8HiddenValue::getHiddenValue(info .GetIsolate(), info.Callee(), V8HiddenValue::customElementDocument(isolate)).As< v8::Object>());
290 TOSTRING_VOID(V8StringResource<>, namespaceURI, V8HiddenValue::getHiddenValu e(isolate, info.Callee(), V8HiddenValue::customElementNamespaceURI(isolate)));
291 TOSTRING_VOID(V8StringResource<>, tagName, V8HiddenValue::getHiddenValue(iso late, info.Callee(), V8HiddenValue::customElementTagName(isolate)));
292 v8::Handle<v8::Value> maybeType = V8HiddenValue::getHiddenValue(info.GetIsol ate(), info.Callee(), V8HiddenValue::customElementType(isolate));
293 TOSTRING_VOID(V8StringResource<>, type, maybeType);
294
295 ExceptionState exceptionState(ExceptionState::ConstructionContext, "CustomEl ement", info.Holder(), info.GetIsolate());
296 CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
297 RefPtrWillBeRawPtr<Element> element = document->createElementNS(namespaceURI , tagName, maybeType->IsNull() ? nullAtom : type, exceptionState);
298 if (exceptionState.throwIfNeeded())
299 return;
300 v8SetReturnValueFast(info, element.release(), document);
301 }
302
303 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/bindings/v8/CustomElementConstructorBuilder.h ('k') | Source/bindings/v8/CustomElementWrapper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698