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 // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregis
try-get | 129 // https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregis
try-get |
116 ScriptValue CustomElementsRegistry::get(const AtomicString& name) | 130 ScriptValue CustomElementsRegistry::get(const AtomicString& name) |
117 { | 131 { |
118 CustomElementDefinition* definition = definitionForName(name); | 132 CustomElementDefinition* definition = definitionForName(name); |
119 if (!definition) { | 133 if (!definition) { |
120 // Binding layer converts |ScriptValue()| to script specific value, | 134 // Binding layer converts |ScriptValue()| to script specific value, |
121 // e.g. |undefined| for v8. | 135 // e.g. |undefined| for v8. |
122 return ScriptValue(); | 136 return ScriptValue(); |
123 } | 137 } |
124 return definition->getConstructorForScript(); | 138 return definition->getConstructorForScript(); |
125 } | 139 } |
126 | 140 |
127 bool CustomElementsRegistry::v0NameIsDefined(const AtomicString& name) const | 141 bool CustomElementsRegistry::nameIsDefined(const AtomicString& name) const |
128 { | 142 { |
129 if (!m_v0) | 143 return m_definitions.contains(name); |
130 return false; | 144 } |
131 return m_v0->nameIsDefined(name); | 145 |
| 146 V0CustomElementRegistrationContext* CustomElementsRegistry::v0() |
| 147 { |
| 148 return m_document->registrationContext(); |
| 149 } |
| 150 |
| 151 bool CustomElementsRegistry::v0NameIsDefined(const AtomicString& name) |
| 152 { |
| 153 if (V0CustomElementRegistrationContext* v0Context = v0()) |
| 154 return v0Context->nameIsDefined(name); |
| 155 return false; |
132 } | 156 } |
133 | 157 |
134 CustomElementDefinition* CustomElementsRegistry::definitionForName( | 158 CustomElementDefinition* CustomElementsRegistry::definitionForName( |
135 const AtomicString& name) const | 159 const AtomicString& name) const |
136 { | 160 { |
137 return m_definitions.get(name); | 161 return m_definitions.get(name); |
138 } | 162 } |
139 | 163 |
| 164 void CustomElementsRegistry::addCandidate(Element* candidate) |
| 165 { |
| 166 const AtomicString& name = candidate->localName(); |
| 167 if (nameIsDefined(name) || v0NameIsDefined(name)) |
| 168 return; |
| 169 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(name); |
| 170 UpgradeCandidateSet* set; |
| 171 if (it != m_upgradeCandidates->end()) { |
| 172 set = it->value; |
| 173 } else { |
| 174 set = m_upgradeCandidates->add(name, new UpgradeCandidateSet()) |
| 175 .storedValue |
| 176 ->value; |
| 177 } |
| 178 set->add(candidate); |
| 179 } |
| 180 |
| 181 void CustomElementsRegistry::collectCandidates( |
| 182 const CustomElementDescriptor& desc, |
| 183 HeapVector<Member<Element>>* elements) |
| 184 { |
| 185 UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(desc.name()); |
| 186 if (it == m_upgradeCandidates->end()) |
| 187 return; |
| 188 CustomElementUpgradeSorter sorter; |
| 189 for (Element* element : *it.get()->value) { |
| 190 if (!element || !desc.matches(*element)) |
| 191 continue; |
| 192 sorter.add(element); |
| 193 } |
| 194 |
| 195 m_upgradeCandidates->remove(it); |
| 196 sorter.sorted(elements, m_document.get()); |
| 197 } |
| 198 |
140 } // namespace blink | 199 } // namespace blink |
OLD | NEW |