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/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 "core/dom/Document.h" | 9 #include "core/dom/Document.h" |
10 #include "core/dom/Element.h" | |
10 #include "core/dom/ElementRegistrationOptions.h" | 11 #include "core/dom/ElementRegistrationOptions.h" |
11 #include "core/dom/ExceptionCode.h" | 12 #include "core/dom/ExceptionCode.h" |
13 #include "core/dom/custom/CEReactionsScope.h" | |
12 #include "core/dom/custom/CustomElement.h" | 14 #include "core/dom/custom/CustomElement.h" |
13 #include "core/dom/custom/CustomElementDefinition.h" | 15 #include "core/dom/custom/CustomElementDefinition.h" |
14 #include "core/dom/custom/CustomElementDefinitionBuilder.h" | 16 #include "core/dom/custom/CustomElementDefinitionBuilder.h" |
17 #include "core/dom/custom/CustomElementDescriptor.h" | |
18 #include "core/dom/custom/CustomElementUpgradeReaction.h" | |
19 #include "core/dom/custom/CustomElementUpgradeSorter.h" | |
15 #include "core/dom/custom/V0CustomElementRegistrationContext.h" | 20 #include "core/dom/custom/V0CustomElementRegistrationContext.h" |
16 | 21 |
17 namespace blink { | 22 namespace blink { |
18 | 23 |
19 CustomElementsRegistry* CustomElementsRegistry::create( | 24 CustomElementsRegistry* CustomElementsRegistry::create( |
20 V0CustomElementRegistrationContext* v0) | 25 Document* document) |
21 { | 26 { |
22 // TODO(dominicc): The window could install a new document; add a signal | 27 CustomElementsRegistry* registry = new CustomElementsRegistry(document); |
23 // when a window installs a new document to notify that V0 context, too. | 28 if (V0CustomElementRegistrationContext* v0Context = registry->v0()) |
24 CustomElementsRegistry* registry = new CustomElementsRegistry(v0); | 29 v0Context->setV1(registry); |
25 if (v0) | |
26 v0->setV1(registry); | |
27 return registry; | 30 return registry; |
28 } | 31 } |
29 | 32 |
30 CustomElementsRegistry::CustomElementsRegistry( | 33 CustomElementsRegistry::CustomElementsRegistry(Document* document) |
31 const V0CustomElementRegistrationContext* v0) | 34 : m_document(document) |
32 : m_v0(v0) | 35 , m_upgradeCandidates(new UpgradeCandidateMap()) |
33 { | 36 { |
34 } | 37 } |
35 | 38 |
36 DEFINE_TRACE(CustomElementsRegistry) | 39 DEFINE_TRACE(CustomElementsRegistry) |
37 { | 40 { |
38 visitor->trace(m_definitions); | 41 visitor->trace(m_definitions); |
39 visitor->trace(m_v0); | 42 visitor->trace(m_document); |
43 visitor->trace(m_upgradeCandidates); | |
40 } | 44 } |
41 | 45 |
42 void CustomElementsRegistry::define( | 46 void CustomElementsRegistry::define( |
43 ScriptState* scriptState, | 47 ScriptState* scriptState, |
44 const AtomicString& name, | 48 const AtomicString& name, |
45 const ScriptValue& constructor, | 49 const ScriptValue& constructor, |
46 const ElementRegistrationOptions& options, | 50 const ElementRegistrationOptions& options, |
47 ExceptionState& exceptionState) | 51 ExceptionState& exceptionState) |
48 { | 52 { |
49 ScriptCustomElementDefinitionBuilder builder( | 53 ScriptCustomElementDefinitionBuilder builder( |
50 scriptState, | 54 scriptState, |
51 this, | 55 this, |
52 constructor, | 56 constructor, |
53 exceptionState); | 57 exceptionState); |
54 define(name, builder, options, exceptionState); | 58 define(name, builder, options, exceptionState); |
55 } | 59 } |
56 | 60 |
57 // http://w3c.github.io/webcomponents/spec/custom/#dfn-element-definition | 61 // http://w3c.github.io/webcomponents/spec/custom/#dfn-element-definition |
58 void CustomElementsRegistry::define( | 62 void CustomElementsRegistry::define( |
59 const AtomicString& name, | 63 const AtomicString& name, |
60 CustomElementDefinitionBuilder& builder, | 64 CustomElementDefinitionBuilder& builder, |
61 const ElementRegistrationOptions& options, | 65 const ElementRegistrationOptions& options, |
62 ExceptionState& exceptionState) | 66 ExceptionState& exceptionState) |
63 { | 67 { |
68 CEReactionsScope reactions; | |
69 | |
64 if (!builder.checkConstructorIntrinsics()) | 70 if (!builder.checkConstructorIntrinsics()) |
65 return; | 71 return; |
66 | 72 |
67 if (!CustomElement::isValidName(name)) { | 73 if (!CustomElement::isValidName(name)) { |
68 exceptionState.throwDOMException( | 74 exceptionState.throwDOMException( |
69 SyntaxError, | 75 SyntaxError, |
70 "\"" + name + "\" is not a valid custom element name"); | 76 "\"" + name + "\" is not a valid custom element name"); |
71 return; | 77 return; |
72 } | 78 } |
73 | 79 |
(...skipping 27 matching lines...) Expand all Loading... | |
101 // recursively calls define with the same name. | 107 // recursively calls define with the same name. |
102 | 108 |
103 CustomElementDescriptor descriptor(name, name); | 109 CustomElementDescriptor descriptor(name, name); |
104 CustomElementDefinition* definition = builder.build(descriptor); | 110 CustomElementDefinition* definition = builder.build(descriptor); |
105 CHECK(!exceptionState.hadException()); | 111 CHECK(!exceptionState.hadException()); |
106 CHECK(definition->descriptor() == descriptor); | 112 CHECK(definition->descriptor() == descriptor); |
107 DefinitionMap::AddResult result = | 113 DefinitionMap::AddResult result = |
108 m_definitions.add(descriptor.name(), definition); | 114 m_definitions.add(descriptor.name(), definition); |
109 CHECK(result.isNewEntry); | 115 CHECK(result.isNewEntry); |
110 | 116 |
117 HeapVector<Member<Element>> candidates; | |
118 collectCandidates(descriptor, &candidates); | |
119 for (Element* candidate : candidates) { | |
120 reactions.enqueue( | |
121 candidate, | |
122 new CustomElementUpgradeReaction(definition)); | |
123 } | |
124 | |
111 // TODO(dominicc): Implement steps: | 125 // TODO(dominicc): Implement steps: |
112 // 20: when-defined promise processing | 126 // 20: when-defined promise processing |
113 } | 127 } |
114 | 128 |
115 bool CustomElementsRegistry::v0NameIsDefined(const AtomicString& name) const | 129 bool CustomElementsRegistry::nameIsDefined(const AtomicString& name) const |
116 { | 130 { |
117 if (!m_v0) | 131 return m_definitions.contains(name); |
118 return false; | 132 } |
119 return m_v0->nameIsDefined(name); | 133 |
134 V0CustomElementRegistrationContext* CustomElementsRegistry::v0() | |
135 { | |
136 return m_document->registrationContext(); | |
137 } | |
138 | |
139 bool CustomElementsRegistry::v0NameIsDefined(const AtomicString& name) | |
140 { | |
141 if (V0CustomElementRegistrationContext* v0Context = v0()) | |
142 return v0Context->nameIsDefined(name); | |
143 return false; | |
144 } | |
145 | |
146 void CustomElementsRegistry::addCandidate(Element* candidate) | |
147 { | |
148 const AtomicString& name = candidate->localName(); | |
149 if (nameIsDefined(name) || v0NameIsDefined(name)) | |
150 return; | |
151 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(name); | |
152 UpgradeCandidateSet* set; | |
153 if (it != m_upgradeCandidates->end()) { | |
154 set = it->value; | |
155 } else { | |
156 set = m_upgradeCandidates->add(name, new UpgradeCandidateSet()) | |
157 .storedValue | |
158 ->value; | |
159 } | |
160 set->add(candidate); | |
161 } | |
162 | |
163 void CustomElementsRegistry::collectCandidates( | |
164 const CustomElementDescriptor& desc, | |
165 HeapVector<Member<Element>>* elements) | |
166 { | |
167 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(desc.name()); | |
168 if (it == m_upgradeCandidates->end()) | |
169 return; | |
170 CustomElementUpgradeSorter sorter; | |
171 for (Element* element : *it.get()->value) { | |
172 // TODO(dominicc): Investigate whether a collection of weak members | |
173 // prunes its storage. If iteration can not return null, then | |
174 // remove this check. | |
175 if (!element) | |
yosin_UTC9
2016/06/02 04:06:38
nit: It is better to use early-continue:
if (!ele
| |
176 continue; | |
177 if (desc.matches(*element)) | |
178 sorter.add(element); | |
179 } | |
180 | |
181 m_upgradeCandidates->remove(it); | |
182 sorter.sorted(elements, m_document.get()); | |
120 } | 183 } |
121 | 184 |
122 CustomElementDefinition* CustomElementsRegistry::definitionForName( | 185 CustomElementDefinition* CustomElementsRegistry::definitionForName( |
123 const AtomicString& name) const | 186 const AtomicString& name) const |
124 { | 187 { |
125 return m_definitions.get(name); | 188 return m_definitions.get(name); |
126 } | 189 } |
127 | 190 |
128 } // namespace blink | 191 } // namespace blink |
OLD | NEW |