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 |