 Chromium Code Reviews
 Chromium Code Reviews Issue 2054433002:
  Implement "create an element" when sync for Custom Element V1  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@async-ce
    
  
    Issue 2054433002:
  Implement "create an element" when sync for Custom Element V1  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@async-ce| 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 { | |
| 
haraken
2016/06/14 01:48:11
You can add DCHECK(ScriptState::current() == m_scr
 
kojii
2016/06/14 07:13:15
Done.
 | |
| 161 // Create an element | |
| 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 = nullptr; | |
| 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 ScriptState::Scope scope(m_scriptState.get()); | |
| 189 v8::Isolate* isolate = m_scriptState->isolate(); | |
| 190 | |
| 191 // When invoked from "create an element for a token": | |
| 192 // https://html.spec.whatwg.org/multipage/syntax.html#create-an-element-for- the-token | |
| 193 // 7. If this step throws an exception, then report the exception, ... | |
| 194 v8::TryCatch tryCatch(isolate); | |
| 195 tryCatch.SetVerbose(true); | |
| 196 ExceptionState exceptionState(ExceptionState::ConstructionContext, "CustomEl ement", constructor(), isolate); | |
| 197 HTMLElement* element = createElementSync(document, tagName, exceptionState); | |
| 198 DCHECK(!tryCatch.HasCaught()); | |
| 199 exceptionState.throwIfNeeded(); | |
| 
haraken
2016/06/14 01:48:11
I still don't understand these lines.
The createE
 
kojii
2016/06/14 07:13:14
Reordered to read easier by reflecting our offline
 | |
| 200 | |
| 201 if (tryCatch.HasCaught() || !element) { | |
| 202 // ...and let element be instead a new element that implements | |
| 203 // HTMLUnknownElement, with no attributes, namespace set to given | |
| 204 // namespace, namespace prefix set to null, custom element state | |
| 205 // "undefined", and node document set to document. | |
| 206 element = HTMLUnknownElement::create(tagName, document); | |
| 207 element->setCustomElementState(CustomElementState::Undefined); | |
| 208 } | |
| 
haraken
2016/06/14 06:42:59
To make the code clearer, let's write this as foll
 | |
| 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); | 
| 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 { | |
| 
haraken
2016/06/14 01:48:11
You can add DCHECK(ScriptState::current() == m_scr
 
kojii
2016/06/14 07:13:15
Done.
 | |
| 246 v8::Isolate* isolate = m_scriptState->isolate(); | |
| 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 |