Index: third_party/WebKit/Source/core/dom/custom/CustomElementsRegistry.cpp |
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElementsRegistry.cpp b/third_party/WebKit/Source/core/dom/custom/CustomElementsRegistry.cpp |
index 618fa6158733ce98c0e8a201fb189d03966b939a..567c4437d19995b34d769d0af70417617a30e07c 100644 |
--- a/third_party/WebKit/Source/core/dom/custom/CustomElementsRegistry.cpp |
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElementsRegistry.cpp |
@@ -4,39 +4,44 @@ |
#include "core/dom/custom/CustomElementsRegistry.h" |
+// TODO: things to remove |
+#include "bindings/core/v8/DOMWrapperWorld.h" |
+ |
#include "bindings/core/v8/ExceptionState.h" |
#include "bindings/core/v8/ScriptCustomElementDefinitionBuilder.h" |
#include "core/dom/Document.h" |
+#include "core/dom/Element.h" |
#include "core/dom/ElementRegistrationOptions.h" |
#include "core/dom/ExceptionCode.h" |
#include "core/dom/custom/CustomElement.h" |
#include "core/dom/custom/CustomElementDefinition.h" |
#include "core/dom/custom/CustomElementDefinitionBuilder.h" |
+#include "core/dom/custom/CustomElementDescriptor.h" |
+#include "core/dom/custom/CustomElementUpgradeSorter.h" |
#include "core/dom/custom/V0CustomElementRegistrationContext.h" |
namespace blink { |
CustomElementsRegistry* CustomElementsRegistry::create( |
- V0CustomElementRegistrationContext* v0) |
+ Document* document) |
{ |
- // TODO(dominicc): The window could install a new document; add a signal |
- // when a window installs a new document to notify that V0 context, too. |
- CustomElementsRegistry* registry = new CustomElementsRegistry(v0); |
- if (v0) |
- v0->setV1(registry); |
+ CustomElementsRegistry* registry = new CustomElementsRegistry(document); |
+ if (V0CustomElementRegistrationContext* v0Context = registry->v0()) |
+ v0Context->setV1(registry); |
return registry; |
} |
-CustomElementsRegistry::CustomElementsRegistry( |
- const V0CustomElementRegistrationContext* v0) |
- : m_v0(v0) |
+CustomElementsRegistry::CustomElementsRegistry(Document* document) |
+ : m_document(document) |
+ , m_upgradeCandidates(new UpgradeCandidateMap()) |
{ |
} |
DEFINE_TRACE(CustomElementsRegistry) |
{ |
visitor->trace(m_definitions); |
- visitor->trace(m_v0); |
+ visitor->trace(m_document); |
+ visitor->trace(m_upgradeCandidates); |
} |
void CustomElementsRegistry::define( |
@@ -108,15 +113,100 @@ void CustomElementsRegistry::define( |
m_definitions.add(descriptor.name(), definition); |
CHECK(result.isNewEntry); |
+ // TODO(dominicc): When we implement other reactions we must move |
+ // this upgrade step so it is mediated by the reactions queue. |
+ HeapVector<Member<Element>> candidates; |
+ collectCandidates(descriptor, &candidates); |
+ for (Element* candidate : candidates) |
+ upgrade(definition, candidate); |
+ |
// TODO(dominicc): Implement steps: |
// 20: when-defined promise processing |
} |
-bool CustomElementsRegistry::v0NameIsDefined(const AtomicString& name) const |
+bool CustomElementsRegistry::nameIsDefined(const AtomicString& name) const |
+{ |
+ return m_definitions.contains(name); |
+} |
+ |
+V0CustomElementRegistrationContext* CustomElementsRegistry::v0() |
+{ |
+ return m_document->registrationContext(); |
+} |
+ |
+bool CustomElementsRegistry::v0NameIsDefined(const AtomicString& name) |
+{ |
+ if (V0CustomElementRegistrationContext* v0Context = v0()) |
+ return v0Context->nameIsDefined(name); |
+ return false; |
+} |
+ |
+void CustomElementsRegistry::addCandidate(Element* candidate) |
+{ |
+ const AtomicString& name = candidate->localName(); |
+ if (nameIsDefined(name) || v0NameIsDefined(name)) |
+ return; |
+ UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(name); |
+ UpgradeCandidateSet* set; |
+ if (it != m_upgradeCandidates->end()) { |
+ set = it->value; |
+ } else { |
+ set = m_upgradeCandidates->add(name, new UpgradeCandidateSet()) |
+ .storedValue |
+ ->value; |
+ } |
+ set->add(candidate); |
+} |
+ |
+void CustomElementsRegistry::collectCandidates( |
+ const CustomElementDescriptor& desc, |
+ HeapVector<Member<Element>>* elements) |
+{ |
+ UpgradeCandidateMap::iterator it = m_upgradeCandidates->find(desc.name()); |
+ if (it == m_upgradeCandidates->end()) |
+ return; |
+ CustomElementUpgradeSorter sorter; |
+ for (Element* element : *it.get()->value) { |
+ // TODO(dominicc): Investigate whether a collection of weak members |
+ // prunes its storage. If iteration can not return null, then |
+ // remove this check. |
+ if (!element) |
+ continue; |
+ if (desc.matches(*element)) |
+ sorter.add(element); |
+ } |
+ |
+ m_upgradeCandidates->remove(it); |
+ sorter.sorted(elements, m_document.get()); |
+} |
+ |
+// TODO(dominicc): Deport this to definitions |
+ |
+// https://html.spec.whatwg.org/multipage/scripting.html#upgrades |
+void CustomElementsRegistry::upgrade( |
+ CustomElementDefinition* def, |
+ Element* element) |
{ |
- if (!m_v0) |
- return false; |
- return m_v0->nameIsDefined(name); |
+ // TODO(dominicc): Consider making this pushing and popping a stack object |
+ size_t depth = def->constructionStack().size(); |
+ def->constructionStack().append(element); |
+ |
+ bool succeeded = def->upgrade(element); |
+ |
+ // Pop the construction stack. |
+ DCHECK(def->constructionStack().last() == element |
+ || !def->constructionStack().last()); |
+ def->constructionStack().removeLast(); |
+ DCHECK(def->constructionStack().size() == depth); |
+ |
+ if (!succeeded) |
+ return; |
+ |
+ element->setCustomElementState(CustomElementState::Custom); |
+ // TODO(dominicc): When the attributeChangedCallback is implemented, |
+ // enqueue reactions for attributes here. |
+ // TODO(dominicc): When the connectedCallback is implemented, enqueue |
+ // reactions here, if applicable. |
} |
CustomElementDefinition* CustomElementsRegistry::definitionForName( |