Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(758)

Side by Side Diff: third_party/WebKit/Source/core/dom/custom/CustomElementsRegistry.cpp

Issue 2048343002: Introduce CustomElementRegistry#whenDefined() method (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 2016-06-10T19:03:11 Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/CustomElementsRegistry.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"
10 #include "bindings/core/v8/ScriptPromiseResolver.h"
9 #include "core/dom/Document.h" 11 #include "core/dom/Document.h"
10 #include "core/dom/Element.h" 12 #include "core/dom/Element.h"
11 #include "core/dom/ElementRegistrationOptions.h" 13 #include "core/dom/ElementRegistrationOptions.h"
12 #include "core/dom/ExceptionCode.h" 14 #include "core/dom/ExceptionCode.h"
13 #include "core/dom/custom/CEReactionsScope.h" 15 #include "core/dom/custom/CEReactionsScope.h"
14 #include "core/dom/custom/CustomElement.h" 16 #include "core/dom/custom/CustomElement.h"
15 #include "core/dom/custom/CustomElementDefinition.h" 17 #include "core/dom/custom/CustomElementDefinition.h"
16 #include "core/dom/custom/CustomElementDefinitionBuilder.h" 18 #include "core/dom/custom/CustomElementDefinitionBuilder.h"
17 #include "core/dom/custom/CustomElementDescriptor.h" 19 #include "core/dom/custom/CustomElementDescriptor.h"
18 #include "core/dom/custom/CustomElementUpgradeReaction.h" 20 #include "core/dom/custom/CustomElementUpgradeReaction.h"
19 #include "core/dom/custom/CustomElementUpgradeSorter.h" 21 #include "core/dom/custom/CustomElementUpgradeSorter.h"
20 #include "core/dom/custom/V0CustomElementRegistrationContext.h" 22 #include "core/dom/custom/V0CustomElementRegistrationContext.h"
21 #include "wtf/Allocator.h" 23 #include "wtf/Allocator.h"
22 24
23 namespace blink { 25 namespace blink {
24 26
27 // Returns true if |name| is invalid.
28 static bool throwIfInvalidName(
29 const AtomicString& name,
30 ExceptionState& exceptionState)
31 {
32 if (CustomElement::isValidName(name))
33 return false;
34 exceptionState.throwDOMException(
35 SyntaxError,
36 "\"" + name + "\" is not a valid custom element name");
37 return true;
38 }
39
40
25 class CustomElementsRegistry::NameIsBeingDefined final { 41 class CustomElementsRegistry::NameIsBeingDefined final {
26 STACK_ALLOCATED(); 42 STACK_ALLOCATED();
27 DISALLOW_IMPLICIT_CONSTRUCTORS(NameIsBeingDefined); 43 DISALLOW_IMPLICIT_CONSTRUCTORS(NameIsBeingDefined);
28 public: 44 public:
29 NameIsBeingDefined( 45 NameIsBeingDefined(
30 CustomElementsRegistry* registry, 46 CustomElementsRegistry* registry,
31 const AtomicString& name) 47 const AtomicString& name)
32 : m_registry(registry) 48 : m_registry(registry)
33 , m_name(name) 49 , m_name(name)
34 { 50 {
(...skipping 24 matching lines...) Expand all
59 : m_document(document) 75 : m_document(document)
60 , m_upgradeCandidates(new UpgradeCandidateMap()) 76 , m_upgradeCandidates(new UpgradeCandidateMap())
61 { 77 {
62 } 78 }
63 79
64 DEFINE_TRACE(CustomElementsRegistry) 80 DEFINE_TRACE(CustomElementsRegistry)
65 { 81 {
66 visitor->trace(m_definitions); 82 visitor->trace(m_definitions);
67 visitor->trace(m_document); 83 visitor->trace(m_document);
68 visitor->trace(m_upgradeCandidates); 84 visitor->trace(m_upgradeCandidates);
85 visitor->trace(m_whenDefinedPromiseMap);
69 } 86 }
70 87
71 void CustomElementsRegistry::define( 88 void CustomElementsRegistry::define(
72 ScriptState* scriptState, 89 ScriptState* scriptState,
73 const AtomicString& name, 90 const AtomicString& name,
74 const ScriptValue& constructor, 91 const ScriptValue& constructor,
75 const ElementRegistrationOptions& options, 92 const ElementRegistrationOptions& options,
76 ExceptionState& exceptionState) 93 ExceptionState& exceptionState)
77 { 94 {
78 ScriptCustomElementDefinitionBuilder builder( 95 ScriptCustomElementDefinitionBuilder builder(
79 scriptState, 96 scriptState,
80 this, 97 this,
81 constructor, 98 constructor,
82 exceptionState); 99 exceptionState);
83 define(name, builder, options, exceptionState); 100 define(name, builder, options, exceptionState);
84 } 101 }
85 102
86 // http://w3c.github.io/webcomponents/spec/custom/#dfn-element-definition 103 // http://w3c.github.io/webcomponents/spec/custom/#dfn-element-definition
87 void CustomElementsRegistry::define( 104 void CustomElementsRegistry::define(
88 const AtomicString& name, 105 const AtomicString& name,
89 CustomElementDefinitionBuilder& builder, 106 CustomElementDefinitionBuilder& builder,
90 const ElementRegistrationOptions& options, 107 const ElementRegistrationOptions& options,
91 ExceptionState& exceptionState) 108 ExceptionState& exceptionState)
92 { 109 {
93 if (!builder.checkConstructorIntrinsics()) 110 if (!builder.checkConstructorIntrinsics())
94 return; 111 return;
95 112
96 if (!CustomElement::isValidName(name)) { 113 if (throwIfInvalidName(name, exceptionState))
97 exceptionState.throwDOMException(
98 SyntaxError,
99 "\"" + name + "\" is not a valid custom element name");
100 return; 114 return;
101 }
102 115
103 if (m_namesBeingDefined.contains(name)) { 116 if (m_namesBeingDefined.contains(name)) {
104 exceptionState.throwDOMException( 117 exceptionState.throwDOMException(
105 NotSupportedError, 118 NotSupportedError,
106 "this name is already being defined in this registry"); 119 "this name is already being defined in this registry");
107 return; 120 return;
108 } 121 }
109 NameIsBeingDefined defining(this, name); 122 NameIsBeingDefined defining(this, name);
110 123
111 if (nameIsDefined(name) || v0NameIsDefined(name)) { 124 if (nameIsDefined(name) || v0NameIsDefined(name)) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 CHECK(definition->descriptor() == descriptor); 162 CHECK(definition->descriptor() == descriptor);
150 DefinitionMap::AddResult result = 163 DefinitionMap::AddResult result =
151 m_definitions.add(descriptor.name(), definition); 164 m_definitions.add(descriptor.name(), definition);
152 CHECK(result.isNewEntry); 165 CHECK(result.isNewEntry);
153 166
154 HeapVector<Member<Element>> candidates; 167 HeapVector<Member<Element>> candidates;
155 collectCandidates(descriptor, &candidates); 168 collectCandidates(descriptor, &candidates);
156 for (Element* candidate : candidates) 169 for (Element* candidate : candidates)
157 CustomElement::enqueueUpgradeReaction(candidate, definition); 170 CustomElement::enqueueUpgradeReaction(candidate, definition);
158 171
159 // TODO(dominicc): Implement steps: 172 // 19: when-defined promise processing
160 // 20: when-defined promise processing 173 const auto& entry = m_whenDefinedPromiseMap.find(name);
174 if (entry == m_whenDefinedPromiseMap.end())
175 return;
176 entry->value->resolve();
177 m_whenDefinedPromiseMap.remove(entry);
161 } 178 }
162 179
163 // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregis try-get 180 // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregis try-get
164 ScriptValue CustomElementsRegistry::get(const AtomicString& name) 181 ScriptValue CustomElementsRegistry::get(const AtomicString& name)
165 { 182 {
166 CustomElementDefinition* definition = definitionForName(name); 183 CustomElementDefinition* definition = definitionForName(name);
167 if (!definition) { 184 if (!definition) {
168 // Binding layer converts |ScriptValue()| to script specific value, 185 // Binding layer converts |ScriptValue()| to script specific value,
169 // e.g. |undefined| for v8. 186 // e.g. |undefined| for v8.
170 return ScriptValue(); 187 return ScriptValue();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 if (it != m_upgradeCandidates->end()) { 222 if (it != m_upgradeCandidates->end()) {
206 set = it->value; 223 set = it->value;
207 } else { 224 } else {
208 set = m_upgradeCandidates->add(name, new UpgradeCandidateSet()) 225 set = m_upgradeCandidates->add(name, new UpgradeCandidateSet())
209 .storedValue 226 .storedValue
210 ->value; 227 ->value;
211 } 228 }
212 set->add(candidate); 229 set->add(candidate);
213 } 230 }
214 231
232 // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregis try-whendefined
233 ScriptPromise CustomElementsRegistry::whenDefined(
234 ScriptState* scriptState,
235 const AtomicString& name,
236 ExceptionState& exceptionState)
237 {
238 if (throwIfInvalidName(name, exceptionState))
239 return ScriptPromise();
240 CustomElementDefinition* definition = definitionForName(name);
241 if (definition)
242 return ScriptPromise::castUndefined(scriptState);
243 ScriptPromiseResolver* resolver = m_whenDefinedPromiseMap.get(name);
244 if (resolver)
245 return resolver->promise();
246 ScriptPromiseResolver* newResolver =
247 ScriptPromiseResolver::create(scriptState);
248 m_whenDefinedPromiseMap.add(name, newResolver);
249 return newResolver->promise();
250 }
251
215 void CustomElementsRegistry::collectCandidates( 252 void CustomElementsRegistry::collectCandidates(
216 const CustomElementDescriptor& desc, 253 const CustomElementDescriptor& desc,
217 HeapVector<Member<Element>>* elements) 254 HeapVector<Member<Element>>* elements)
218 { 255 {
219 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(desc.name()); 256 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(desc.name());
220 if (it == m_upgradeCandidates->end()) 257 if (it == m_upgradeCandidates->end())
221 return; 258 return;
222 CustomElementUpgradeSorter sorter; 259 CustomElementUpgradeSorter sorter;
223 for (Element* element : *it.get()->value) { 260 for (Element* element : *it.get()->value) {
224 if (!element || !desc.matches(*element)) 261 if (!element || !desc.matches(*element))
225 continue; 262 continue;
226 sorter.add(element); 263 sorter.add(element);
227 } 264 }
228 265
229 m_upgradeCandidates->remove(it); 266 m_upgradeCandidates->remove(it);
230 sorter.sorted(elements, m_document.get()); 267 sorter.sorted(elements, m_document.get());
231 } 268 }
232 269
233 } // namespace blink 270 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698