Clean up some includes to make the build a bit faster: DOMPromise
[WebKit-https.git] / Source / WebCore / dom / CustomElementRegistry.cpp
1 /*
2  * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "CustomElementRegistry.h"
28
29 #include "CustomElementReactionQueue.h"
30 #include "DOMWindow.h"
31 #include "Document.h"
32 #include "Element.h"
33 #include "ElementTraversal.h"
34 #include "JSCustomElementInterface.h"
35 #include "JSDOMPromiseDeferred.h"
36 #include "MathMLNames.h"
37 #include "QualifiedName.h"
38 #include "ShadowRoot.h"
39 #include "TypedElementDescendantIterator.h"
40 #include <JavaScriptCore/JSCJSValueInlines.h>
41 #include <wtf/text/AtomString.h>
42
43 namespace WebCore {
44
45 Ref<CustomElementRegistry> CustomElementRegistry::create(DOMWindow& window, ScriptExecutionContext* scriptExecutionContext)
46 {
47     return adoptRef(*new CustomElementRegistry(window, scriptExecutionContext));
48 }
49
50 CustomElementRegistry::CustomElementRegistry(DOMWindow& window, ScriptExecutionContext* scriptExecutionContext)
51     : ContextDestructionObserver(scriptExecutionContext)
52     , m_window(window)
53 {
54 }
55
56 CustomElementRegistry::~CustomElementRegistry() = default;
57
58 // https://dom.spec.whatwg.org/#concept-shadow-including-tree-order
59 static void enqueueUpgradeInShadowIncludingTreeOrder(ContainerNode& node, JSCustomElementInterface& elementInterface)
60 {
61     for (Element* element = ElementTraversal::firstWithin(node); element; element = ElementTraversal::next(*element)) {
62         if (element->isCustomElementUpgradeCandidate() && element->tagQName() == elementInterface.name())
63             element->enqueueToUpgrade(elementInterface);
64         if (auto* shadowRoot = element->shadowRoot()) {
65             if (shadowRoot->mode() != ShadowRootMode::UserAgent)
66                 enqueueUpgradeInShadowIncludingTreeOrder(*shadowRoot, elementInterface);
67         }
68     }
69 }
70
71 void CustomElementRegistry::addElementDefinition(Ref<JSCustomElementInterface>&& elementInterface)
72 {
73     AtomString localName = elementInterface->name().localName();
74     ASSERT(!m_nameMap.contains(localName));
75     m_constructorMap.add(elementInterface->constructor(), elementInterface.ptr());
76     m_nameMap.add(localName, elementInterface.copyRef());
77
78     if (auto* document = m_window.document())
79         enqueueUpgradeInShadowIncludingTreeOrder(*document, elementInterface.get());
80
81     if (auto promise = m_promiseMap.take(localName))
82         promise.value()->resolve();
83 }
84
85 JSCustomElementInterface* CustomElementRegistry::findInterface(const Element& element) const
86 {
87     return findInterface(element.tagQName());
88 }
89
90 JSCustomElementInterface* CustomElementRegistry::findInterface(const QualifiedName& name) const
91 {
92     if (name.namespaceURI() != HTMLNames::xhtmlNamespaceURI)
93         return nullptr;
94     return m_nameMap.get(name.localName());
95 }
96
97 JSCustomElementInterface* CustomElementRegistry::findInterface(const AtomString& name) const
98 {
99     return m_nameMap.get(name);
100 }
101
102 JSCustomElementInterface* CustomElementRegistry::findInterface(const JSC::JSObject* constructor) const
103 {
104     return m_constructorMap.get(constructor);
105 }
106
107 bool CustomElementRegistry::containsConstructor(const JSC::JSObject* constructor) const
108 {
109     return m_constructorMap.contains(constructor);
110 }
111
112 JSC::JSValue CustomElementRegistry::get(const AtomString& name)
113 {
114     if (auto* elementInterface = m_nameMap.get(name))
115         return elementInterface->constructor();
116     return JSC::jsUndefined();
117 }
118
119 static void upgradeElementsInShadowIncludingDescendants(ContainerNode& root)
120 {
121     for (auto& element : descendantsOfType<Element>(root)) {
122         if (element.isCustomElementUpgradeCandidate())
123             CustomElementReactionQueue::enqueueElementUpgradeIfDefined(element);
124         if (auto* shadowRoot = element.shadowRoot())
125             upgradeElementsInShadowIncludingDescendants(*shadowRoot);
126     }
127 }
128
129 void CustomElementRegistry::upgrade(Node& root)
130 {
131     if (!is<ContainerNode>(root))
132         return;
133
134     if (is<Element>(root) && downcast<Element>(root).isCustomElementUpgradeCandidate())
135         CustomElementReactionQueue::enqueueElementUpgradeIfDefined(downcast<Element>(root));
136
137     upgradeElementsInShadowIncludingDescendants(downcast<ContainerNode>(root));
138 }
139
140 }