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

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

Issue 2306923002: Prevent recursion in critical part of CustomElementRegistry::define. (Closed)
Patch Set: Feedback Created 4 years, 3 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
« no previous file with comments | « third_party/WebKit/Source/core/dom/custom/CustomElementRegistry.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/CustomElementRegistry.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"
(...skipping 21 matching lines...) Expand all
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 CustomElementRegistry::NameIsBeingDefined final { 42 class CustomElementRegistry::ElementDefinitionIsRunning final {
43 STACK_ALLOCATED(); 43 STACK_ALLOCATED();
44 DISALLOW_IMPLICIT_CONSTRUCTORS(NameIsBeingDefined); 44 DISALLOW_IMPLICIT_CONSTRUCTORS(ElementDefinitionIsRunning);
45 public: 45 public:
46 NameIsBeingDefined( 46 ElementDefinitionIsRunning(bool& flag)
47 CustomElementRegistry* registry, 47 : m_flag(flag)
48 const AtomicString& name)
49 : m_registry(registry)
50 , m_name(name)
51 { 48 {
52 DCHECK(!m_registry->m_namesBeingDefined.contains(name)); 49 DCHECK(!m_flag);
53 m_registry->m_namesBeingDefined.add(name); 50 m_flag = true;
54 } 51 }
55 52
56 ~NameIsBeingDefined() 53 ~ElementDefinitionIsRunning()
57 { 54 {
58 m_registry->m_namesBeingDefined.remove(m_name); 55 DCHECK(m_flag);
56 m_flag = false;
59 } 57 }
60 58
61 private: 59 private:
62 Member<CustomElementRegistry> m_registry; 60 bool& m_flag;
63 const AtomicString& m_name;
64 }; 61 };
65 62
66 CustomElementRegistry* CustomElementRegistry::create( 63 CustomElementRegistry* CustomElementRegistry::create(
67 const LocalDOMWindow* owner) 64 const LocalDOMWindow* owner)
68 { 65 {
69 CustomElementRegistry* registry = new CustomElementRegistry(owner); 66 CustomElementRegistry* registry = new CustomElementRegistry(owner);
70 Document* document = owner->document(); 67 Document* document = owner->document();
71 if (V0CustomElementRegistrationContext* v0 = 68 if (V0CustomElementRegistrationContext* v0 =
72 document ? document->registrationContext() : nullptr) 69 document ? document->registrationContext() : nullptr)
73 registry->entangle(v0); 70 registry->entangle(v0);
74 return registry; 71 return registry;
75 } 72 }
76 73
77 CustomElementRegistry::CustomElementRegistry(const LocalDOMWindow* owner) 74 CustomElementRegistry::CustomElementRegistry(const LocalDOMWindow* owner)
78 : m_owner(owner) 75 : m_elementDefinitionIsRunning(false)
76 , m_owner(owner)
79 , m_v0 (new V0RegistrySet()) 77 , m_v0 (new V0RegistrySet())
80 , m_upgradeCandidates(new UpgradeCandidateMap()) 78 , m_upgradeCandidates(new UpgradeCandidateMap())
81 { 79 {
82 } 80 }
83 81
84 DEFINE_TRACE(CustomElementRegistry) 82 DEFINE_TRACE(CustomElementRegistry)
85 { 83 {
86 visitor->trace(m_definitions); 84 visitor->trace(m_definitions);
87 visitor->trace(m_owner); 85 visitor->trace(m_owner);
88 visitor->trace(m_v0); 86 visitor->trace(m_v0);
(...skipping 22 matching lines...) Expand all
111 CustomElementDefinitionBuilder& builder, 109 CustomElementDefinitionBuilder& builder,
112 const ElementRegistrationOptions& options, 110 const ElementRegistrationOptions& options,
113 ExceptionState& exceptionState) 111 ExceptionState& exceptionState)
114 { 112 {
115 if (!builder.checkConstructorIntrinsics()) 113 if (!builder.checkConstructorIntrinsics())
116 return; 114 return;
117 115
118 if (throwIfInvalidName(name, exceptionState)) 116 if (throwIfInvalidName(name, exceptionState))
119 return; 117 return;
120 118
121 if (m_namesBeingDefined.contains(name)) {
122 exceptionState.throwDOMException(
123 NotSupportedError,
124 "this name is already being defined in this registry");
125 return;
126 }
127 NameIsBeingDefined defining(this, name);
128
129 if (nameIsDefined(name) || v0NameIsDefined(name)) { 119 if (nameIsDefined(name) || v0NameIsDefined(name)) {
130 exceptionState.throwDOMException( 120 exceptionState.throwDOMException(
131 NotSupportedError, 121 NotSupportedError,
132 "this name has already been used with this registry"); 122 "this name has already been used with this registry");
133 return; 123 return;
134 } 124 }
135 125
136 if (!builder.checkConstructorNotRegistered()) 126 if (!builder.checkConstructorNotRegistered())
137 return; 127 return;
138 128
139 // TODO(dominicc): Implement steps: 129 // TODO(dominicc): Implement steps 6-7 for customized built-in elements
140 // 5: localName
141 // 6-7: extends processing
142
143 // 8-9: observed attributes caching is done below, together with callbacks.
144 // TODO(kojii): https://github.com/whatwg/html/issues/1373 for the ordering.
145 // When it's resolved, revisit if this code needs changes.
146 130
147 // TODO(dominicc): Add a test where the prototype getter destroys 131 // TODO(dominicc): Add a test where the prototype getter destroys
148 // the context. 132 // the context.
149 133
150 if (!builder.checkPrototype()) 134 // 8. If this CustomElementRegistry's element definition is
135 // running flag is set, then throw a "NotSupportedError"
136 // DOMException and abort these steps.
137 if (m_elementDefinitionIsRunning) {
138 exceptionState.throwDOMException(
139 NotSupportedError,
140 "an element definition is already being processed");
151 return; 141 return;
142 }
152 143
153 // 8-9: observed attributes caching 144 {
154 // 12-13: connected callback 145 // 9. Set this CustomElementRegistry's element definition is
155 // 14-15: disconnected callback 146 // running flag.
156 // 16-17: attribute changed callback 147 ElementDefinitionIsRunning defining(m_elementDefinitionIsRunning);
157 148
158 if (!builder.rememberOriginalProperties()) 149 // 10.1-2
159 return; 150 if (!builder.checkPrototype())
151 return;
160 152
161 // TODO(dominicc): Add a test where retrieving the prototype 153 // 10.3-6
162 // recursively calls define with the same name. 154 if (!builder.rememberOriginalProperties())
155 return;
156
157 // "Then, perform the following substep, regardless of whether
158 // the above steps threw an exception or not: Unset this
159 // CustomElementRegistry's element definition is running
160 // flag."
161 // (ElementDefinitionIsRunning destructor does this.)
162 }
163 163
164 CustomElementDescriptor descriptor(name, name); 164 CustomElementDescriptor descriptor(name, name);
165 CustomElementDefinition* definition = builder.build(descriptor); 165 CustomElementDefinition* definition = builder.build(descriptor);
166 CHECK(!exceptionState.hadException()); 166 CHECK(!exceptionState.hadException());
167 CHECK(definition->descriptor() == descriptor); 167 CHECK(definition->descriptor() == descriptor);
168 DefinitionMap::AddResult result = 168 DefinitionMap::AddResult result =
169 m_definitions.add(descriptor.name(), definition); 169 m_definitions.add(descriptor.name(), definition);
170 CHECK(result.isNewEntry); 170 CHECK(result.isNewEntry);
171 171
172 HeapVector<Member<Element>> candidates; 172 HeapVector<Member<Element>> candidates;
173 collectCandidates(descriptor, &candidates); 173 collectCandidates(descriptor, &candidates);
174 for (Element* candidate : candidates) 174 for (Element* candidate : candidates)
175 definition->enqueueUpgradeReaction(candidate); 175 definition->enqueueUpgradeReaction(candidate);
176 176
177 // 19: when-defined promise processing 177 // 16: 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 CustomElementRegistry::get(const AtomicString& name) 186 ScriptValue CustomElementRegistry::get(const AtomicString& name)
187 { 187 {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/custom/CustomElementRegistry.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698