OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "bindings/core/v8/ScriptCustomElementDefinition.h" | 5 #include "bindings/core/v8/ScriptCustomElementDefinition.h" |
6 | 6 |
7 #include "bindings/core/v8/ScriptState.h" | 7 #include "bindings/core/v8/ScriptState.h" |
8 #include "bindings/core/v8/V8Binding.h" | 8 #include "bindings/core/v8/V8Binding.h" |
9 #include "bindings/core/v8/V8BindingMacros.h" | 9 #include "bindings/core/v8/V8BindingMacros.h" |
10 #include "bindings/core/v8/V8CustomElementsRegistry.h" | 10 #include "bindings/core/v8/V8CustomElementsRegistry.h" |
11 #include "bindings/core/v8/V8Element.h" | 11 #include "bindings/core/v8/V8Element.h" |
12 #include "bindings/core/v8/V8HiddenValue.h" | 12 #include "bindings/core/v8/V8HiddenValue.h" |
13 #include "bindings/core/v8/V8ScriptRunner.h" | 13 #include "bindings/core/v8/V8ScriptRunner.h" |
14 #include "bindings/core/v8/V8ThrowException.h" | 14 #include "bindings/core/v8/V8ThrowException.h" |
15 #include "core/dom/ExceptionCode.h" | 15 #include "core/dom/ExceptionCode.h" |
16 #include "core/html/HTMLElement.h" | |
17 #include "core/html/HTMLUnknownElement.h" | |
16 #include "v8.h" | 18 #include "v8.h" |
17 #include "wtf/Allocator.h" | 19 #include "wtf/Allocator.h" |
18 | 20 |
19 namespace blink { | 21 namespace blink { |
20 | 22 |
21 // Retrieves the custom elements constructor -> name map, creating it | 23 // Retrieves the custom elements constructor -> name map, creating it |
22 // if necessary. The same map is used to keep prototypes alive. | 24 // if necessary. The same map is used to keep prototypes alive. |
23 static v8::Local<v8::Map> ensureCustomElementsRegistryMap( | 25 static v8::Local<v8::Map> ensureCustomElementsRegistryMap( |
24 ScriptState* scriptState, | 26 ScriptState* scriptState, |
25 CustomElementsRegistry* registry) | 27 CustomElementsRegistry* registry) |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
145 const v8::Local<v8::Object>& disconnectedCallback, | 147 const v8::Local<v8::Object>& disconnectedCallback, |
146 const v8::Local<v8::Object>& attributeChangedCallback, | 148 const v8::Local<v8::Object>& attributeChangedCallback, |
147 const HashSet<AtomicString>& observedAttributes) | 149 const HashSet<AtomicString>& observedAttributes) |
148 : CustomElementDefinition(descriptor) | 150 : CustomElementDefinition(descriptor) |
149 , m_scriptState(scriptState) | 151 , m_scriptState(scriptState) |
150 , m_constructor(scriptState->isolate(), constructor) | 152 , m_constructor(scriptState->isolate(), constructor) |
151 , m_observedAttributes(observedAttributes) | 153 , m_observedAttributes(observedAttributes) |
152 { | 154 { |
153 } | 155 } |
154 | 156 |
157 HTMLElement* ScriptCustomElementDefinition::createElementSync( | |
158 Document& document, const QualifiedName& tagName, | |
159 ExceptionState& exceptionState) | |
160 { | |
161 // Create an element | |
haraken
2016/06/13 09:05:35
Is it guaranteed that you're already in m_scriptSt
kojii
2016/06/13 10:28:25
Yes, that's the assumption atm; we assume DOM crea
| |
162 // https://dom.spec.whatwg.org/#concept-create-element | |
163 // 6. If definition is non-null | |
164 // 6.1. If the synchronous custom elements flag is set: | |
165 // 6.1.2. Set result to Construct(C). Rethrow any exceptions. | |
166 Element* element; | |
haraken
2016/06/13 09:05:35
element = nullptr
kojii
2016/06/13 10:28:25
Will fix in the next CL.
| |
167 { | |
168 v8::TryCatch tryCatch(m_scriptState->isolate()); | |
169 element = runConstructor(); | |
170 if (tryCatch.HasCaught()) { | |
171 exceptionState.rethrowV8Exception(tryCatch.Exception()); | |
172 return nullptr; | |
173 } | |
174 } | |
175 | |
176 // 6.1.3. through 6.1.9. | |
177 checkConstructorResult(element, document, tagName, exceptionState); | |
178 if (exceptionState.hadException()) | |
179 return nullptr; | |
180 | |
181 DCHECK_EQ(element->getCustomElementState(), CustomElementState::Custom); | |
182 return toHTMLElement(element); | |
183 } | |
184 | |
185 HTMLElement* ScriptCustomElementDefinition::createElementSync( | |
186 Document& document, const QualifiedName& tagName) | |
187 { | |
188 // When invoked from "create an element for a token": | |
189 // https://html.spec.whatwg.org/multipage/syntax.html#create-an-element-for- the-token | |
190 // 7. If this step throws an exception, then report the exception, and | |
191 // let element be instead a new element that implements HTMLUnknownElement, | |
192 // with no attributes, namespace set to given namespace, namespace prefix | |
193 // set to null, custom element state "undefined", and node document set to | |
194 // document. | |
195 ScriptState::Scope scope(m_scriptState.get()); | |
196 v8::Isolate* isolate = m_scriptState->isolate(); | |
197 v8::TryCatch tryCatch(isolate); | |
haraken
2016/06/13 09:05:35
Why do you need this TryCatch?
| |
198 tryCatch.SetVerbose(true); | |
haraken
2016/06/13 09:05:35
Remove this line unless you really want to make it
kojii
2016/06/13 10:28:25
The spec (copied in the comment above) says catch
| |
199 ExceptionState exceptionState(ExceptionState::ConstructionContext, "CustomEl ement", constructor(), isolate); | |
200 | |
201 HTMLElement* element = createElementSync(document, tagName, exceptionState); | |
202 DCHECK(!tryCatch.HasCaught()); | |
haraken
2016/06/13 09:05:35
Instead, you can check DCHECK(!exceptionState.hadE
kojii
2016/06/13 10:28:25
There are errors here when JS throws. The purpose
| |
203 | |
204 exceptionState.throwIfNeeded(); | |
205 if (tryCatch.HasCaught() || !element) { | |
206 element = HTMLUnknownElement::create(tagName, document); | |
207 element->setCustomElementState(CustomElementState::Undefined); | |
208 } | |
209 return element; | |
210 } | |
211 | |
155 // https://html.spec.whatwg.org/multipage/scripting.html#upgrades | 212 // https://html.spec.whatwg.org/multipage/scripting.html#upgrades |
156 bool ScriptCustomElementDefinition::runConstructor(Element* element) | 213 bool ScriptCustomElementDefinition::runConstructor(Element* element) |
157 { | 214 { |
158 if (!m_scriptState->contextIsValid()) | 215 if (!m_scriptState->contextIsValid()) |
159 return false; | 216 return false; |
160 ScriptState::Scope scope(m_scriptState.get()); | 217 ScriptState::Scope scope(m_scriptState.get()); |
161 v8::Isolate* isolate = m_scriptState->isolate(); | 218 v8::Isolate* isolate = m_scriptState->isolate(); |
162 | 219 |
163 // Step 5 says to rethrow the exception; but there is no one to | 220 // Step 5 says to rethrow the exception; but there is no one to |
164 // catch it. The side effect is to report the error. | 221 // catch it. The side effect is to report the error. |
165 v8::TryCatch tryCatch(isolate); | 222 v8::TryCatch tryCatch(isolate); |
166 tryCatch.SetVerbose(true); | 223 tryCatch.SetVerbose(true); |
haraken
2016/06/13 09:05:35
Remove this line.
kojii
2016/06/13 10:28:25
The spec requires to "report the error" here, as i
| |
167 | 224 |
168 ExecutionContext* executionContext = m_scriptState->getExecutionContext(); | 225 Element* result = runConstructor(); |
169 v8::Local<v8::Value> result; | 226 if (!result) |
170 if (!v8Call(V8ScriptRunner::callAsConstructor( | |
171 isolate, | |
172 constructor(), | |
173 executionContext, | |
174 0, | |
175 nullptr), | |
176 result)) | |
177 return false; | 227 return false; |
178 | 228 |
179 if (V8Element::toImplWithTypeCheck(isolate, result) != element) { | 229 if (result != element) { |
180 V8ThrowException::throwException( | 230 V8ThrowException::throwException( |
181 V8ThrowException::createDOMException( | 231 V8ThrowException::createDOMException( |
182 m_scriptState->isolate(), | 232 m_scriptState->isolate(), |
183 InvalidStateError, | 233 InvalidStateError, |
184 "custom element constructors must call super() first and must " | 234 "custom element constructors must call super() first and must " |
185 "not return a different object", | 235 "not return a different object", |
186 constructor()), | 236 constructor()), |
187 m_scriptState->isolate()); | 237 m_scriptState->isolate()); |
188 return false; | 238 return false; |
189 } | 239 } |
190 | 240 |
191 return true; | 241 return true; |
192 } | 242 } |
193 | 243 |
244 Element* ScriptCustomElementDefinition::runConstructor() | |
245 { | |
246 v8::Isolate* isolate = m_scriptState->isolate(); | |
haraken
2016/06/13 09:05:35
Is it guaranteed that you're already in m_scriptSt
kojii
2016/06/13 10:28:25
Yes, this is called from either:
1. createElement
| |
247 ExecutionContext* executionContext = m_scriptState->getExecutionContext(); | |
248 v8::Local<v8::Value> result; | |
249 if (!v8Call(V8ScriptRunner::callAsConstructor( | |
250 isolate, | |
251 constructor(), | |
252 executionContext, | |
253 0, | |
254 nullptr), | |
255 result)) { | |
256 return nullptr; | |
257 } | |
258 return V8Element::toImplWithTypeCheck(isolate, result); | |
259 } | |
260 | |
194 v8::Local<v8::Object> ScriptCustomElementDefinition::constructor() const | 261 v8::Local<v8::Object> ScriptCustomElementDefinition::constructor() const |
195 { | 262 { |
196 DCHECK(!m_constructor.isEmpty()); | 263 DCHECK(!m_constructor.isEmpty()); |
197 return m_constructor.newLocal(m_scriptState->isolate()); | 264 return m_constructor.newLocal(m_scriptState->isolate()); |
198 } | 265 } |
199 | 266 |
200 v8::Local<v8::Object> ScriptCustomElementDefinition::prototype() const | 267 v8::Local<v8::Object> ScriptCustomElementDefinition::prototype() const |
201 { | 268 { |
202 DCHECK(!m_prototype.isEmpty()); | 269 DCHECK(!m_prototype.isEmpty()); |
203 return m_prototype.newLocal(m_scriptState->isolate()); | 270 return m_prototype.newLocal(m_scriptState->isolate()); |
204 } | 271 } |
205 | 272 |
206 // CustomElementDefinition | 273 // CustomElementDefinition |
207 ScriptValue ScriptCustomElementDefinition::getConstructorForScript() | 274 ScriptValue ScriptCustomElementDefinition::getConstructorForScript() |
208 { | 275 { |
209 return ScriptValue(m_scriptState.get(), constructor()); | 276 return ScriptValue(m_scriptState.get(), constructor()); |
210 } | 277 } |
211 | 278 |
212 } // namespace blink | 279 } // namespace blink |
OLD | NEW |