| 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 "core/dom/custom/CustomElementsRegistry.h" | 5 #include "core/dom/custom/CustomElementRegistry.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/ExceptionState.h" | 7 #include "bindings/core/v8/ExceptionState.h" |
| 8 #include "bindings/core/v8/ScriptCustomElementDefinitionBuilder.h" | 8 #include "bindings/core/v8/ScriptCustomElementDefinitionBuilder.h" |
| 9 #include "bindings/core/v8/ScriptPromise.h" | 9 #include "bindings/core/v8/ScriptPromise.h" |
| 10 #include "bindings/core/v8/ScriptPromiseResolver.h" | 10 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 11 #include "core/dom/Document.h" | 11 #include "core/dom/Document.h" |
| 12 #include "core/dom/Element.h" | 12 #include "core/dom/Element.h" |
| 13 #include "core/dom/ElementRegistrationOptions.h" | 13 #include "core/dom/ElementRegistrationOptions.h" |
| 14 #include "core/dom/ExceptionCode.h" | 14 #include "core/dom/ExceptionCode.h" |
| 15 #include "core/dom/custom/CEReactionsScope.h" | 15 #include "core/dom/custom/CEReactionsScope.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 32 { | 32 { |
| 33 if (CustomElement::isValidName(name)) | 33 if (CustomElement::isValidName(name)) |
| 34 return false; | 34 return false; |
| 35 exceptionState.throwDOMException( | 35 exceptionState.throwDOMException( |
| 36 SyntaxError, | 36 SyntaxError, |
| 37 "\"" + name + "\" is not a valid custom element name"); | 37 "\"" + name + "\" is not a valid custom element name"); |
| 38 return true; | 38 return true; |
| 39 } | 39 } |
| 40 | 40 |
| 41 | 41 |
| 42 class CustomElementsRegistry::NameIsBeingDefined final { | 42 class CustomElementRegistry::NameIsBeingDefined final { |
| 43 STACK_ALLOCATED(); | 43 STACK_ALLOCATED(); |
| 44 DISALLOW_IMPLICIT_CONSTRUCTORS(NameIsBeingDefined); | 44 DISALLOW_IMPLICIT_CONSTRUCTORS(NameIsBeingDefined); |
| 45 public: | 45 public: |
| 46 NameIsBeingDefined( | 46 NameIsBeingDefined( |
| 47 CustomElementsRegistry* registry, | 47 CustomElementRegistry* registry, |
| 48 const AtomicString& name) | 48 const AtomicString& name) |
| 49 : m_registry(registry) | 49 : m_registry(registry) |
| 50 , m_name(name) | 50 , m_name(name) |
| 51 { | 51 { |
| 52 DCHECK(!m_registry->m_namesBeingDefined.contains(name)); | 52 DCHECK(!m_registry->m_namesBeingDefined.contains(name)); |
| 53 m_registry->m_namesBeingDefined.add(name); | 53 m_registry->m_namesBeingDefined.add(name); |
| 54 } | 54 } |
| 55 | 55 |
| 56 ~NameIsBeingDefined() | 56 ~NameIsBeingDefined() |
| 57 { | 57 { |
| 58 m_registry->m_namesBeingDefined.remove(m_name); | 58 m_registry->m_namesBeingDefined.remove(m_name); |
| 59 } | 59 } |
| 60 | 60 |
| 61 private: | 61 private: |
| 62 Member<CustomElementsRegistry> m_registry; | 62 Member<CustomElementRegistry> m_registry; |
| 63 const AtomicString& m_name; | 63 const AtomicString& m_name; |
| 64 }; | 64 }; |
| 65 | 65 |
| 66 CustomElementsRegistry* CustomElementsRegistry::create( | 66 CustomElementRegistry* CustomElementRegistry::create( |
| 67 const LocalDOMWindow* owner) | 67 const LocalDOMWindow* owner) |
| 68 { | 68 { |
| 69 CustomElementsRegistry* registry = new CustomElementsRegistry(owner); | 69 CustomElementRegistry* registry = new CustomElementRegistry(owner); |
| 70 Document* document = owner->document(); | 70 Document* document = owner->document(); |
| 71 if (V0CustomElementRegistrationContext* v0 = | 71 if (V0CustomElementRegistrationContext* v0 = |
| 72 document ? document->registrationContext() : nullptr) | 72 document ? document->registrationContext() : nullptr) |
| 73 registry->entangle(v0); | 73 registry->entangle(v0); |
| 74 return registry; | 74 return registry; |
| 75 } | 75 } |
| 76 | 76 |
| 77 CustomElementsRegistry::CustomElementsRegistry(const LocalDOMWindow* owner) | 77 CustomElementRegistry::CustomElementRegistry(const LocalDOMWindow* owner) |
| 78 : m_owner(owner) | 78 : m_owner(owner) |
| 79 , m_v0 (new V0RegistrySet()) | 79 , m_v0 (new V0RegistrySet()) |
| 80 , m_upgradeCandidates(new UpgradeCandidateMap()) | 80 , m_upgradeCandidates(new UpgradeCandidateMap()) |
| 81 { | 81 { |
| 82 } | 82 } |
| 83 | 83 |
| 84 DEFINE_TRACE(CustomElementsRegistry) | 84 DEFINE_TRACE(CustomElementRegistry) |
| 85 { | 85 { |
| 86 visitor->trace(m_definitions); | 86 visitor->trace(m_definitions); |
| 87 visitor->trace(m_owner); | 87 visitor->trace(m_owner); |
| 88 visitor->trace(m_v0); | 88 visitor->trace(m_v0); |
| 89 visitor->trace(m_upgradeCandidates); | 89 visitor->trace(m_upgradeCandidates); |
| 90 visitor->trace(m_whenDefinedPromiseMap); | 90 visitor->trace(m_whenDefinedPromiseMap); |
| 91 } | 91 } |
| 92 | 92 |
| 93 void CustomElementsRegistry::define( | 93 void CustomElementRegistry::define( |
| 94 ScriptState* scriptState, | 94 ScriptState* scriptState, |
| 95 const AtomicString& name, | 95 const AtomicString& name, |
| 96 const ScriptValue& constructor, | 96 const ScriptValue& constructor, |
| 97 const ElementRegistrationOptions& options, | 97 const ElementRegistrationOptions& options, |
| 98 ExceptionState& exceptionState) | 98 ExceptionState& exceptionState) |
| 99 { | 99 { |
| 100 ScriptCustomElementDefinitionBuilder builder( | 100 ScriptCustomElementDefinitionBuilder builder( |
| 101 scriptState, | 101 scriptState, |
| 102 this, | 102 this, |
| 103 constructor, | 103 constructor, |
| 104 exceptionState); | 104 exceptionState); |
| 105 define(name, builder, options, exceptionState); | 105 define(name, builder, options, exceptionState); |
| 106 } | 106 } |
| 107 | 107 |
| 108 // http://w3c.github.io/webcomponents/spec/custom/#dfn-element-definition | 108 // http://w3c.github.io/webcomponents/spec/custom/#dfn-element-definition |
| 109 void CustomElementsRegistry::define( | 109 void CustomElementRegistry::define( |
| 110 const AtomicString& name, | 110 const AtomicString& name, |
| 111 CustomElementDefinitionBuilder& builder, | 111 CustomElementDefinitionBuilder& builder, |
| 112 const ElementRegistrationOptions& options, | 112 const ElementRegistrationOptions& options, |
| 113 ExceptionState& exceptionState) | 113 ExceptionState& exceptionState) |
| 114 { | 114 { |
| 115 if (!builder.checkConstructorIntrinsics()) | 115 if (!builder.checkConstructorIntrinsics()) |
| 116 return; | 116 return; |
| 117 | 117 |
| 118 if (throwIfInvalidName(name, exceptionState)) | 118 if (throwIfInvalidName(name, exceptionState)) |
| 119 return; | 119 return; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 | 176 |
| 177 // 19: when-defined promise processing | 177 // 19: when-defined promise processing |
| 178 const auto& entry = m_whenDefinedPromiseMap.find(name); | 178 const auto& entry = m_whenDefinedPromiseMap.find(name); |
| 179 if (entry == m_whenDefinedPromiseMap.end()) | 179 if (entry == m_whenDefinedPromiseMap.end()) |
| 180 return; | 180 return; |
| 181 entry->value->resolve(); | 181 entry->value->resolve(); |
| 182 m_whenDefinedPromiseMap.remove(entry); | 182 m_whenDefinedPromiseMap.remove(entry); |
| 183 } | 183 } |
| 184 | 184 |
| 185 // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregis
try-get | 185 // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregis
try-get |
| 186 ScriptValue CustomElementsRegistry::get(const AtomicString& name) | 186 ScriptValue CustomElementRegistry::get(const AtomicString& name) |
| 187 { | 187 { |
| 188 CustomElementDefinition* definition = definitionForName(name); | 188 CustomElementDefinition* definition = definitionForName(name); |
| 189 if (!definition) { | 189 if (!definition) { |
| 190 // Binding layer converts |ScriptValue()| to script specific value, | 190 // Binding layer converts |ScriptValue()| to script specific value, |
| 191 // e.g. |undefined| for v8. | 191 // e.g. |undefined| for v8. |
| 192 return ScriptValue(); | 192 return ScriptValue(); |
| 193 } | 193 } |
| 194 return definition->getConstructorForScript(); | 194 return definition->getConstructorForScript(); |
| 195 } | 195 } |
| 196 | 196 |
| 197 CustomElementDefinition* CustomElementsRegistry::definitionFor(const CustomEleme
ntDescriptor& desc) const | 197 CustomElementDefinition* CustomElementRegistry::definitionFor(const CustomElemen
tDescriptor& desc) const |
| 198 { | 198 { |
| 199 CustomElementDefinition* definition = definitionForName(desc.name()); | 199 CustomElementDefinition* definition = definitionForName(desc.name()); |
| 200 if (!definition) | 200 if (!definition) |
| 201 return nullptr; | 201 return nullptr; |
| 202 // The definition for a customized built-in element, such as | 202 // The definition for a customized built-in element, such as |
| 203 // <button is="my-button"> should not be provided for an | 203 // <button is="my-button"> should not be provided for an |
| 204 // autonomous element, such as <my-button>, even though the | 204 // autonomous element, such as <my-button>, even though the |
| 205 // name "my-button" matches. | 205 // name "my-button" matches. |
| 206 return definition->descriptor() == desc ? definition : nullptr; | 206 return definition->descriptor() == desc ? definition : nullptr; |
| 207 } | 207 } |
| 208 | 208 |
| 209 bool CustomElementsRegistry::nameIsDefined(const AtomicString& name) const | 209 bool CustomElementRegistry::nameIsDefined(const AtomicString& name) const |
| 210 { | 210 { |
| 211 return m_definitions.contains(name); | 211 return m_definitions.contains(name); |
| 212 } | 212 } |
| 213 | 213 |
| 214 void CustomElementsRegistry::entangle(V0CustomElementRegistrationContext* v0) | 214 void CustomElementRegistry::entangle(V0CustomElementRegistrationContext* v0) |
| 215 { | 215 { |
| 216 m_v0->add(v0); | 216 m_v0->add(v0); |
| 217 v0->setV1(this); | 217 v0->setV1(this); |
| 218 } | 218 } |
| 219 | 219 |
| 220 bool CustomElementsRegistry::v0NameIsDefined(const AtomicString& name) | 220 bool CustomElementRegistry::v0NameIsDefined(const AtomicString& name) |
| 221 { | 221 { |
| 222 for (const auto& v0 : *m_v0) { | 222 for (const auto& v0 : *m_v0) { |
| 223 if (v0->nameIsDefined(name)) | 223 if (v0->nameIsDefined(name)) |
| 224 return true; | 224 return true; |
| 225 } | 225 } |
| 226 return false; | 226 return false; |
| 227 } | 227 } |
| 228 | 228 |
| 229 CustomElementDefinition* CustomElementsRegistry::definitionForName( | 229 CustomElementDefinition* CustomElementRegistry::definitionForName( |
| 230 const AtomicString& name) const | 230 const AtomicString& name) const |
| 231 { | 231 { |
| 232 return m_definitions.get(name); | 232 return m_definitions.get(name); |
| 233 } | 233 } |
| 234 | 234 |
| 235 void CustomElementsRegistry::addCandidate(Element* candidate) | 235 void CustomElementRegistry::addCandidate(Element* candidate) |
| 236 { | 236 { |
| 237 const AtomicString& name = candidate->localName(); | 237 const AtomicString& name = candidate->localName(); |
| 238 if (nameIsDefined(name) || v0NameIsDefined(name)) | 238 if (nameIsDefined(name) || v0NameIsDefined(name)) |
| 239 return; | 239 return; |
| 240 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(name); | 240 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(name); |
| 241 UpgradeCandidateSet* set; | 241 UpgradeCandidateSet* set; |
| 242 if (it != m_upgradeCandidates->end()) { | 242 if (it != m_upgradeCandidates->end()) { |
| 243 set = it->value; | 243 set = it->value; |
| 244 } else { | 244 } else { |
| 245 set = m_upgradeCandidates->add(name, new UpgradeCandidateSet()) | 245 set = m_upgradeCandidates->add(name, new UpgradeCandidateSet()) |
| 246 .storedValue | 246 .storedValue |
| 247 ->value; | 247 ->value; |
| 248 } | 248 } |
| 249 set->add(candidate); | 249 set->add(candidate); |
| 250 } | 250 } |
| 251 | 251 |
| 252 // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregis
try-whendefined | 252 // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregis
try-whendefined |
| 253 ScriptPromise CustomElementsRegistry::whenDefined( | 253 ScriptPromise CustomElementRegistry::whenDefined( |
| 254 ScriptState* scriptState, | 254 ScriptState* scriptState, |
| 255 const AtomicString& name, | 255 const AtomicString& name, |
| 256 ExceptionState& exceptionState) | 256 ExceptionState& exceptionState) |
| 257 { | 257 { |
| 258 if (throwIfInvalidName(name, exceptionState)) | 258 if (throwIfInvalidName(name, exceptionState)) |
| 259 return ScriptPromise(); | 259 return ScriptPromise(); |
| 260 CustomElementDefinition* definition = definitionForName(name); | 260 CustomElementDefinition* definition = definitionForName(name); |
| 261 if (definition) | 261 if (definition) |
| 262 return ScriptPromise::castUndefined(scriptState); | 262 return ScriptPromise::castUndefined(scriptState); |
| 263 ScriptPromiseResolver* resolver = m_whenDefinedPromiseMap.get(name); | 263 ScriptPromiseResolver* resolver = m_whenDefinedPromiseMap.get(name); |
| 264 if (resolver) | 264 if (resolver) |
| 265 return resolver->promise(); | 265 return resolver->promise(); |
| 266 ScriptPromiseResolver* newResolver = | 266 ScriptPromiseResolver* newResolver = |
| 267 ScriptPromiseResolver::create(scriptState); | 267 ScriptPromiseResolver::create(scriptState); |
| 268 m_whenDefinedPromiseMap.add(name, newResolver); | 268 m_whenDefinedPromiseMap.add(name, newResolver); |
| 269 return newResolver->promise(); | 269 return newResolver->promise(); |
| 270 } | 270 } |
| 271 | 271 |
| 272 void CustomElementsRegistry::collectCandidates( | 272 void CustomElementRegistry::collectCandidates( |
| 273 const CustomElementDescriptor& desc, | 273 const CustomElementDescriptor& desc, |
| 274 HeapVector<Member<Element>>* elements) | 274 HeapVector<Member<Element>>* elements) |
| 275 { | 275 { |
| 276 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(desc.name()); | 276 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(desc.name()); |
| 277 if (it == m_upgradeCandidates->end()) | 277 if (it == m_upgradeCandidates->end()) |
| 278 return; | 278 return; |
| 279 CustomElementUpgradeSorter sorter; | 279 CustomElementUpgradeSorter sorter; |
| 280 for (Element* element : *it.get()->value) { | 280 for (Element* element : *it.get()->value) { |
| 281 if (!element || !desc.matches(*element)) | 281 if (!element || !desc.matches(*element)) |
| 282 continue; | 282 continue; |
| 283 sorter.add(element); | 283 sorter.add(element); |
| 284 } | 284 } |
| 285 | 285 |
| 286 m_upgradeCandidates->remove(it); | 286 m_upgradeCandidates->remove(it); |
| 287 | 287 |
| 288 Document* document = m_owner->document(); | 288 Document* document = m_owner->document(); |
| 289 if (!document) | 289 if (!document) |
| 290 return; | 290 return; |
| 291 | 291 |
| 292 sorter.sorted(elements, document); | 292 sorter.sorted(elements, document); |
| 293 } | 293 } |
| 294 | 294 |
| 295 } // namespace blink | 295 } // namespace blink |
| OLD | NEW |