Build cleanly with GCC 9
[WebKit-https.git] / Source / WebCore / dom / MutationRecord.cpp
1 /*
2  * Copyright (C) 2011 Google 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "MutationRecord.h"
33
34 #include "CharacterData.h"
35 #include "JSNode.h"
36 #include "StaticNodeList.h"
37 #include <wtf/NeverDestroyed.h>
38 #include <wtf/StdLibExtras.h>
39
40 namespace WebCore {
41
42 namespace {
43
44 static void visitNodeList(JSC::SlotVisitor& visitor, NodeList& nodeList)
45 {
46     ASSERT(!nodeList.isLiveNodeList());
47     unsigned length = nodeList.length();
48     for (unsigned i = 0; i < length; ++i)
49         visitor.addOpaqueRoot(root(nodeList.item(i)));
50 }
51
52 class ChildListRecord final : public MutationRecord {
53 public:
54     ChildListRecord(ContainerNode& target, Ref<NodeList>&& added, Ref<NodeList>&& removed, RefPtr<Node>&& previousSibling, RefPtr<Node>&& nextSibling)
55         : m_target(target)
56         , m_addedNodes(WTFMove(added))
57         , m_removedNodes(WTFMove(removed))
58         , m_previousSibling(WTFMove(previousSibling))
59         , m_nextSibling(WTFMove(nextSibling))
60     {
61     }
62
63 private:
64     const AtomicString& type() override;
65     Node* target() override { return m_target.ptr(); }
66     NodeList* addedNodes() override { return m_addedNodes.get(); }
67     NodeList* removedNodes() override { return m_removedNodes.get(); }
68     Node* previousSibling() override { return m_previousSibling.get(); }
69     Node* nextSibling() override { return m_nextSibling.get(); }
70
71     void visitNodesConcurrently(JSC::SlotVisitor& visitor) const final
72     {
73         visitor.addOpaqueRoot(root(m_target.ptr()));
74         if (m_addedNodes)
75             visitNodeList(visitor, *m_addedNodes);
76         if (m_removedNodes)
77             visitNodeList(visitor, *m_removedNodes);
78     }
79     
80     Ref<ContainerNode> m_target;
81     RefPtr<NodeList> m_addedNodes;
82     RefPtr<NodeList> m_removedNodes;
83     RefPtr<Node> m_previousSibling;
84     RefPtr<Node> m_nextSibling;
85 };
86
87 class RecordWithEmptyNodeLists : public MutationRecord {
88 public:
89     RecordWithEmptyNodeLists(Node& target, const String& oldValue)
90         : m_target(target)
91         , m_oldValue(oldValue)
92     {
93     }
94
95 private:
96     Node* target() override { return m_target.ptr(); }
97     String oldValue() override { return m_oldValue; }
98     NodeList* addedNodes() override { return lazilyInitializeEmptyNodeList(m_addedNodes); }
99     NodeList* removedNodes() override { return lazilyInitializeEmptyNodeList(m_removedNodes); }
100
101     static NodeList* lazilyInitializeEmptyNodeList(RefPtr<NodeList>& nodeList)
102     {
103         if (!nodeList)
104             nodeList = StaticNodeList::create();
105         return nodeList.get();
106     }
107
108     void visitNodesConcurrently(JSC::SlotVisitor& visitor) const final
109     {
110         visitor.addOpaqueRoot(root(m_target.ptr()));
111     }
112
113     Ref<Node> m_target;
114     String m_oldValue;
115     RefPtr<NodeList> m_addedNodes;
116     RefPtr<NodeList> m_removedNodes;
117 };
118
119 class AttributesRecord final : public RecordWithEmptyNodeLists {
120 public:
121     AttributesRecord(Element& target, const QualifiedName& name, const AtomicString& oldValue)
122         : RecordWithEmptyNodeLists(target, oldValue)
123         , m_attributeName(name.localName())
124         , m_attributeNamespace(name.namespaceURI())
125     {
126     }
127
128 private:
129     const AtomicString& type() override;
130     const AtomicString& attributeName() override { return m_attributeName; }
131     const AtomicString& attributeNamespace() override { return m_attributeNamespace; }
132
133     AtomicString m_attributeName;
134     AtomicString m_attributeNamespace;
135 };
136
137 class CharacterDataRecord : public RecordWithEmptyNodeLists {
138 public:
139     CharacterDataRecord(CharacterData& target, const String& oldValue)
140         : RecordWithEmptyNodeLists(target, oldValue)
141     {
142     }
143
144 private:
145     const AtomicString& type() override;
146 };
147
148 class MutationRecordWithNullOldValue final : public MutationRecord {
149 public:
150     MutationRecordWithNullOldValue(MutationRecord& record)
151         : m_record(record)
152     {
153     }
154
155 private:
156     const AtomicString& type() override { return m_record->type(); }
157     Node* target() override { return m_record->target(); }
158     NodeList* addedNodes() override { return m_record->addedNodes(); }
159     NodeList* removedNodes() override { return m_record->removedNodes(); }
160     Node* previousSibling() override { return m_record->previousSibling(); }
161     Node* nextSibling() override { return m_record->nextSibling(); }
162     const AtomicString& attributeName() override { return m_record->attributeName(); }
163     const AtomicString& attributeNamespace() override { return m_record->attributeNamespace(); }
164
165     String oldValue() override { return String(); }
166
167     void visitNodesConcurrently(JSC::SlotVisitor& visitor) const final
168     {
169         m_record->visitNodesConcurrently(visitor);
170     }
171
172     Ref<MutationRecord> m_record;
173 };
174
175 const AtomicString& ChildListRecord::type()
176 {
177     static NeverDestroyed<AtomicString> childList("childList", AtomicString::ConstructFromLiteral);
178     return childList;
179 }
180
181 const AtomicString& AttributesRecord::type()
182 {
183     static NeverDestroyed<AtomicString> attributes("attributes", AtomicString::ConstructFromLiteral);
184     return attributes;
185 }
186
187 const AtomicString& CharacterDataRecord::type()
188 {
189     static NeverDestroyed<AtomicString> characterData("characterData", AtomicString::ConstructFromLiteral);
190     return characterData;
191 }
192
193 } // namespace
194
195 Ref<MutationRecord> MutationRecord::createChildList(ContainerNode& target, Ref<NodeList>&& added, Ref<NodeList>&& removed, RefPtr<Node>&& previousSibling, RefPtr<Node>&& nextSibling)
196 {
197     return adoptRef(static_cast<MutationRecord&>(*new ChildListRecord(target, WTFMove(added), WTFMove(removed), WTFMove(previousSibling), WTFMove(nextSibling))));
198 }
199
200 Ref<MutationRecord> MutationRecord::createAttributes(Element& target, const QualifiedName& name, const AtomicString& oldValue)
201 {
202     return adoptRef(static_cast<MutationRecord&>(*new AttributesRecord(target, name, oldValue)));
203 }
204
205 Ref<MutationRecord> MutationRecord::createCharacterData(CharacterData& target, const String& oldValue)
206 {
207     return adoptRef(static_cast<MutationRecord&>(*new CharacterDataRecord(target, oldValue)));
208 }
209
210 Ref<MutationRecord> MutationRecord::createWithNullOldValue(MutationRecord& record)
211 {
212     return adoptRef(static_cast<MutationRecord&>(*new MutationRecordWithNullOldValue(record)));
213 }
214
215 MutationRecord::~MutationRecord() = default;
216
217 } // namespace WebCore