| 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/CustomElementRegistry.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" |
| (...skipping 21 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 CustomElementRegistry::NameIsBeingDefined final { | 42 class CustomElementRegistry::ElementDefinitionIsRunning final { |
| 43 STACK_ALLOCATED(); | 43 STACK_ALLOCATED(); |
| 44 DISALLOW_IMPLICIT_CONSTRUCTORS(NameIsBeingDefined); | 44 DISALLOW_IMPLICIT_CONSTRUCTORS(ElementDefinitionIsRunning); |
| 45 public: | 45 public: |
| 46 NameIsBeingDefined( | 46 ElementDefinitionIsRunning(bool& flag) |
| 47 CustomElementRegistry* registry, | 47 : m_flag(flag) |
| 48 const AtomicString& name) | |
| 49 : m_registry(registry) | |
| 50 , m_name(name) | |
| 51 { | 48 { |
| 52 DCHECK(!m_registry->m_namesBeingDefined.contains(name)); | 49 DCHECK(!m_flag); |
| 53 m_registry->m_namesBeingDefined.add(name); | 50 m_flag = true; |
| 54 } | 51 } |
| 55 | 52 |
| 56 ~NameIsBeingDefined() | 53 ~ElementDefinitionIsRunning() |
| 57 { | 54 { |
| 58 m_registry->m_namesBeingDefined.remove(m_name); | 55 DCHECK(m_flag); |
| 56 m_flag = false; |
| 59 } | 57 } |
| 60 | 58 |
| 61 private: | 59 private: |
| 62 Member<CustomElementRegistry> m_registry; | 60 bool& m_flag; |
| 63 const AtomicString& m_name; | |
| 64 }; | 61 }; |
| 65 | 62 |
| 66 CustomElementRegistry* CustomElementRegistry::create( | 63 CustomElementRegistry* CustomElementRegistry::create( |
| 67 const LocalDOMWindow* owner) | 64 const LocalDOMWindow* owner) |
| 68 { | 65 { |
| 69 CustomElementRegistry* registry = new CustomElementRegistry(owner); | 66 CustomElementRegistry* registry = new CustomElementRegistry(owner); |
| 70 Document* document = owner->document(); | 67 Document* document = owner->document(); |
| 71 if (V0CustomElementRegistrationContext* v0 = | 68 if (V0CustomElementRegistrationContext* v0 = |
| 72 document ? document->registrationContext() : nullptr) | 69 document ? document->registrationContext() : nullptr) |
| 73 registry->entangle(v0); | 70 registry->entangle(v0); |
| 74 return registry; | 71 return registry; |
| 75 } | 72 } |
| 76 | 73 |
| 77 CustomElementRegistry::CustomElementRegistry(const LocalDOMWindow* owner) | 74 CustomElementRegistry::CustomElementRegistry(const LocalDOMWindow* owner) |
| 78 : m_owner(owner) | 75 : m_elementDefinitionIsRunning(false) |
| 76 , m_owner(owner) |
| 79 , m_v0 (new V0RegistrySet()) | 77 , m_v0 (new V0RegistrySet()) |
| 80 , m_upgradeCandidates(new UpgradeCandidateMap()) | 78 , m_upgradeCandidates(new UpgradeCandidateMap()) |
| 81 { | 79 { |
| 82 } | 80 } |
| 83 | 81 |
| 84 DEFINE_TRACE(CustomElementRegistry) | 82 DEFINE_TRACE(CustomElementRegistry) |
| 85 { | 83 { |
| 86 visitor->trace(m_definitions); | 84 visitor->trace(m_definitions); |
| 87 visitor->trace(m_owner); | 85 visitor->trace(m_owner); |
| 88 visitor->trace(m_v0); | 86 visitor->trace(m_v0); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 111 CustomElementDefinitionBuilder& builder, | 109 CustomElementDefinitionBuilder& builder, |
| 112 const ElementRegistrationOptions& options, | 110 const ElementRegistrationOptions& options, |
| 113 ExceptionState& exceptionState) | 111 ExceptionState& exceptionState) |
| 114 { | 112 { |
| 115 if (!builder.checkConstructorIntrinsics()) | 113 if (!builder.checkConstructorIntrinsics()) |
| 116 return; | 114 return; |
| 117 | 115 |
| 118 if (throwIfInvalidName(name, exceptionState)) | 116 if (throwIfInvalidName(name, exceptionState)) |
| 119 return; | 117 return; |
| 120 | 118 |
| 121 if (m_namesBeingDefined.contains(name)) { | |
| 122 exceptionState.throwDOMException( | |
| 123 NotSupportedError, | |
| 124 "this name is already being defined in this registry"); | |
| 125 return; | |
| 126 } | |
| 127 NameIsBeingDefined defining(this, name); | |
| 128 | |
| 129 if (nameIsDefined(name) || v0NameIsDefined(name)) { | 119 if (nameIsDefined(name) || v0NameIsDefined(name)) { |
| 130 exceptionState.throwDOMException( | 120 exceptionState.throwDOMException( |
| 131 NotSupportedError, | 121 NotSupportedError, |
| 132 "this name has already been used with this registry"); | 122 "this name has already been used with this registry"); |
| 133 return; | 123 return; |
| 134 } | 124 } |
| 135 | 125 |
| 136 if (!builder.checkConstructorNotRegistered()) | 126 if (!builder.checkConstructorNotRegistered()) |
| 137 return; | 127 return; |
| 138 | 128 |
| 139 // TODO(dominicc): Implement steps: | 129 // TODO(dominicc): Implement steps 6-7 for customized built-in elements |
| 140 // 5: localName | |
| 141 // 6-7: extends processing | |
| 142 | |
| 143 // 8-9: observed attributes caching is done below, together with callbacks. | |
| 144 // TODO(kojii): https://github.com/whatwg/html/issues/1373 for the ordering. | |
| 145 // When it's resolved, revisit if this code needs changes. | |
| 146 | 130 |
| 147 // TODO(dominicc): Add a test where the prototype getter destroys | 131 // TODO(dominicc): Add a test where the prototype getter destroys |
| 148 // the context. | 132 // the context. |
| 149 | 133 |
| 150 if (!builder.checkPrototype()) | 134 // 8. If this CustomElementRegistry's element definition is |
| 135 // running flag is set, then throw a "NotSupportedError" |
| 136 // DOMException and abort these steps. |
| 137 if (m_elementDefinitionIsRunning) { |
| 138 exceptionState.throwDOMException( |
| 139 NotSupportedError, |
| 140 "an element definition is already being processed"); |
| 151 return; | 141 return; |
| 142 } |
| 152 | 143 |
| 153 // 8-9: observed attributes caching | 144 { |
| 154 // 12-13: connected callback | 145 // 9. Set this CustomElementRegistry's element definition is |
| 155 // 14-15: disconnected callback | 146 // running flag. |
| 156 // 16-17: attribute changed callback | 147 ElementDefinitionIsRunning defining(m_elementDefinitionIsRunning); |
| 157 | 148 |
| 158 if (!builder.rememberOriginalProperties()) | 149 // 10.1-2 |
| 159 return; | 150 if (!builder.checkPrototype()) |
| 151 return; |
| 160 | 152 |
| 161 // TODO(dominicc): Add a test where retrieving the prototype | 153 // 10.3-6 |
| 162 // recursively calls define with the same name. | 154 if (!builder.rememberOriginalProperties()) |
| 155 return; |
| 156 |
| 157 // "Then, perform the following substep, regardless of whether |
| 158 // the above steps threw an exception or not: Unset this |
| 159 // CustomElementRegistry's element definition is running |
| 160 // flag." |
| 161 // (ElementDefinitionIsRunning destructor does this.) |
| 162 } |
| 163 | 163 |
| 164 CustomElementDescriptor descriptor(name, name); | 164 CustomElementDescriptor descriptor(name, name); |
| 165 CustomElementDefinition* definition = builder.build(descriptor); | 165 CustomElementDefinition* definition = builder.build(descriptor); |
| 166 CHECK(!exceptionState.hadException()); | 166 CHECK(!exceptionState.hadException()); |
| 167 CHECK(definition->descriptor() == descriptor); | 167 CHECK(definition->descriptor() == descriptor); |
| 168 DefinitionMap::AddResult result = | 168 DefinitionMap::AddResult result = |
| 169 m_definitions.add(descriptor.name(), definition); | 169 m_definitions.add(descriptor.name(), definition); |
| 170 CHECK(result.isNewEntry); | 170 CHECK(result.isNewEntry); |
| 171 | 171 |
| 172 HeapVector<Member<Element>> candidates; | 172 HeapVector<Member<Element>> candidates; |
| 173 collectCandidates(descriptor, &candidates); | 173 collectCandidates(descriptor, &candidates); |
| 174 for (Element* candidate : candidates) | 174 for (Element* candidate : candidates) |
| 175 definition->enqueueUpgradeReaction(candidate); | 175 definition->enqueueUpgradeReaction(candidate); |
| 176 | 176 |
| 177 // 19: when-defined promise processing | 177 // 16: 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 CustomElementRegistry::get(const AtomicString& name) | 186 ScriptValue CustomElementRegistry::get(const AtomicString& name) |
| 187 { | 187 { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 |