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 // TODO: things to remove |
| 8 #include "bindings/core/v8/DOMWrapperWorld.h" |
| 9 |
7 #include "bindings/core/v8/ExceptionState.h" | 10 #include "bindings/core/v8/ExceptionState.h" |
8 #include "bindings/core/v8/ScriptCustomElementDefinitionBuilder.h" | 11 #include "bindings/core/v8/ScriptCustomElementDefinitionBuilder.h" |
9 #include "core/dom/Document.h" | 12 #include "core/dom/Document.h" |
| 13 #include "core/dom/Element.h" |
10 #include "core/dom/ElementRegistrationOptions.h" | 14 #include "core/dom/ElementRegistrationOptions.h" |
11 #include "core/dom/ExceptionCode.h" | 15 #include "core/dom/ExceptionCode.h" |
12 #include "core/dom/custom/CustomElement.h" | 16 #include "core/dom/custom/CustomElement.h" |
13 #include "core/dom/custom/CustomElementDefinition.h" | 17 #include "core/dom/custom/CustomElementDefinition.h" |
14 #include "core/dom/custom/CustomElementDefinitionBuilder.h" | 18 #include "core/dom/custom/CustomElementDefinitionBuilder.h" |
| 19 #include "core/dom/custom/CustomElementDescriptor.h" |
| 20 #include "core/dom/custom/CustomElementUpgradeSorter.h" |
15 #include "core/dom/custom/V0CustomElementRegistrationContext.h" | 21 #include "core/dom/custom/V0CustomElementRegistrationContext.h" |
16 | 22 |
17 namespace blink { | 23 namespace blink { |
18 | 24 |
19 CustomElementsRegistry* CustomElementsRegistry::create( | 25 CustomElementsRegistry* CustomElementsRegistry::create( |
20 V0CustomElementRegistrationContext* v0) | 26 Document* document) |
21 { | 27 { |
22 // TODO(dominicc): The window could install a new document; add a signal | 28 CustomElementsRegistry* registry = new CustomElementsRegistry(document); |
23 // when a window installs a new document to notify that V0 context, too. | 29 if (V0CustomElementRegistrationContext* v0Context = registry->v0()) |
24 CustomElementsRegistry* registry = new CustomElementsRegistry(v0); | 30 v0Context->setV1(registry); |
25 if (v0) | |
26 v0->setV1(registry); | |
27 return registry; | 31 return registry; |
28 } | 32 } |
29 | 33 |
30 CustomElementsRegistry::CustomElementsRegistry( | 34 CustomElementsRegistry::CustomElementsRegistry(Document* document) |
31 const V0CustomElementRegistrationContext* v0) | 35 : m_document(document) |
32 : m_v0(v0) | 36 , m_upgradeCandidates(new UpgradeCandidateMap()) |
33 { | 37 { |
34 } | 38 } |
35 | 39 |
36 DEFINE_TRACE(CustomElementsRegistry) | 40 DEFINE_TRACE(CustomElementsRegistry) |
37 { | 41 { |
38 visitor->trace(m_definitions); | 42 visitor->trace(m_definitions); |
39 visitor->trace(m_v0); | 43 visitor->trace(m_document); |
| 44 visitor->trace(m_upgradeCandidates); |
40 } | 45 } |
41 | 46 |
42 void CustomElementsRegistry::define( | 47 void CustomElementsRegistry::define( |
43 ScriptState* scriptState, | 48 ScriptState* scriptState, |
44 const AtomicString& name, | 49 const AtomicString& name, |
45 const ScriptValue& constructor, | 50 const ScriptValue& constructor, |
46 const ElementRegistrationOptions& options, | 51 const ElementRegistrationOptions& options, |
47 ExceptionState& exceptionState) | 52 ExceptionState& exceptionState) |
48 { | 53 { |
49 ScriptCustomElementDefinitionBuilder builder( | 54 ScriptCustomElementDefinitionBuilder builder( |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 // recursively calls define with the same name. | 106 // recursively calls define with the same name. |
102 | 107 |
103 CustomElementDescriptor descriptor(name, name); | 108 CustomElementDescriptor descriptor(name, name); |
104 CustomElementDefinition* definition = builder.build(descriptor); | 109 CustomElementDefinition* definition = builder.build(descriptor); |
105 CHECK(!exceptionState.hadException()); | 110 CHECK(!exceptionState.hadException()); |
106 CHECK(definition->descriptor() == descriptor); | 111 CHECK(definition->descriptor() == descriptor); |
107 DefinitionMap::AddResult result = | 112 DefinitionMap::AddResult result = |
108 m_definitions.add(descriptor.name(), definition); | 113 m_definitions.add(descriptor.name(), definition); |
109 CHECK(result.isNewEntry); | 114 CHECK(result.isNewEntry); |
110 | 115 |
| 116 // TODO(dominicc): When we implement other reactions we must move |
| 117 // this upgrade step so it is mediated by the reactions queue. |
| 118 HeapVector<Member<Element>> candidates; |
| 119 collectCandidates(descriptor, &candidates); |
| 120 for (Element* candidate : candidates) |
| 121 upgrade(definition, candidate); |
| 122 |
111 // TODO(dominicc): Implement steps: | 123 // TODO(dominicc): Implement steps: |
112 // 20: when-defined promise processing | 124 // 20: when-defined promise processing |
113 } | 125 } |
114 | 126 |
115 bool CustomElementsRegistry::v0NameIsDefined(const AtomicString& name) const | 127 bool CustomElementsRegistry::nameIsDefined(const AtomicString& name) const |
116 { | 128 { |
117 if (!m_v0) | 129 return m_definitions.contains(name); |
118 return false; | 130 } |
119 return m_v0->nameIsDefined(name); | 131 |
| 132 V0CustomElementRegistrationContext* CustomElementsRegistry::v0() |
| 133 { |
| 134 return m_document->registrationContext(); |
| 135 } |
| 136 |
| 137 bool CustomElementsRegistry::v0NameIsDefined(const AtomicString& name) |
| 138 { |
| 139 if (V0CustomElementRegistrationContext* v0Context = v0()) |
| 140 return v0Context->nameIsDefined(name); |
| 141 return false; |
| 142 } |
| 143 |
| 144 void CustomElementsRegistry::addCandidate(Element* candidate) |
| 145 { |
| 146 const AtomicString& name = candidate->localName(); |
| 147 if (nameIsDefined(name) || v0NameIsDefined(name)) |
| 148 return; |
| 149 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(name); |
| 150 UpgradeCandidateSet* set; |
| 151 if (it != m_upgradeCandidates->end()) { |
| 152 set = it->value; |
| 153 } else { |
| 154 set = m_upgradeCandidates->add(name, new UpgradeCandidateSet()) |
| 155 .storedValue |
| 156 ->value; |
| 157 } |
| 158 set->add(candidate); |
| 159 } |
| 160 |
| 161 void CustomElementsRegistry::collectCandidates( |
| 162 const CustomElementDescriptor& desc, |
| 163 HeapVector<Member<Element>>* elements) |
| 164 { |
| 165 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(desc.name()); |
| 166 if (it == m_upgradeCandidates->end()) |
| 167 return; |
| 168 CustomElementUpgradeSorter sorter; |
| 169 for (Element* element : *it.get()->value) { |
| 170 // TODO(dominicc): Investigate whether a collection of weak members |
| 171 // prunes its storage. If iteration can not return null, then |
| 172 // remove this check. |
| 173 if (!element) |
| 174 continue; |
| 175 if (desc.matches(*element)) |
| 176 sorter.add(element); |
| 177 } |
| 178 |
| 179 m_upgradeCandidates->remove(it); |
| 180 sorter.sorted(elements, m_document.get()); |
| 181 } |
| 182 |
| 183 // TODO(dominicc): Deport this to definitions |
| 184 |
| 185 // https://html.spec.whatwg.org/multipage/scripting.html#upgrades |
| 186 void CustomElementsRegistry::upgrade( |
| 187 CustomElementDefinition* def, |
| 188 Element* element) |
| 189 { |
| 190 // TODO(dominicc): Consider making this pushing and popping a stack object |
| 191 size_t depth = def->constructionStack().size(); |
| 192 def->constructionStack().append(element); |
| 193 |
| 194 bool succeeded = def->upgrade(element); |
| 195 |
| 196 // Pop the construction stack. |
| 197 DCHECK(def->constructionStack().last() == element |
| 198 || !def->constructionStack().last()); |
| 199 def->constructionStack().removeLast(); |
| 200 DCHECK(def->constructionStack().size() == depth); |
| 201 |
| 202 if (!succeeded) |
| 203 return; |
| 204 |
| 205 element->setCustomElementState(CustomElementState::Custom); |
| 206 // TODO(dominicc): When the attributeChangedCallback is implemented, |
| 207 // enqueue reactions for attributes here. |
| 208 // TODO(dominicc): When the connectedCallback is implemented, enqueue |
| 209 // reactions here, if applicable. |
120 } | 210 } |
121 | 211 |
122 CustomElementDefinition* CustomElementsRegistry::definitionForName( | 212 CustomElementDefinition* CustomElementsRegistry::definitionForName( |
123 const AtomicString& name) const | 213 const AtomicString& name) const |
124 { | 214 { |
125 return m_definitions.get(name); | 215 return m_definitions.get(name); |
126 } | 216 } |
127 | 217 |
128 } // namespace blink | 218 } // namespace blink |
OLD | NEW |