Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / invalidation / DescendantInvalidationSet.cpp
1 /*
2  * Copyright (C) 2014 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 "core/css/invalidation/DescendantInvalidationSet.h"
33
34 #include "core/css/resolver/StyleResolver.h"
35 #include "core/dom/Element.h"
36
37 namespace blink {
38
39 DescendantInvalidationSet::DescendantInvalidationSet()
40     : m_allDescendantsMightBeInvalid(false)
41     , m_customPseudoInvalid(false)
42     , m_treeBoundaryCrossing(false)
43 {
44 }
45
46 bool DescendantInvalidationSet::invalidatesElement(Element& element) const
47 {
48     if (m_allDescendantsMightBeInvalid)
49         return true;
50
51     if (m_tagNames && m_tagNames->contains(element.tagQName().localName()))
52         return true;
53
54     if (element.hasID() && m_ids && m_ids->contains(element.idForStyleResolution()))
55         return true;
56
57     if (element.hasClass() && m_classes) {
58         const SpaceSplitString& classNames = element.classNames();
59         for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_classes->begin(); it != m_classes->end(); ++it) {
60             if (classNames.contains(*it))
61                 return true;
62         }
63     }
64
65     if (element.hasAttributes() && m_attributes) {
66         for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_attributes->begin(); it != m_attributes->end(); ++it) {
67             if (element.hasAttribute(*it))
68                 return true;
69         }
70     }
71
72     return false;
73 }
74
75 void DescendantInvalidationSet::combine(const DescendantInvalidationSet& other)
76 {
77     // No longer bother combining data structures, since the whole subtree is deemed invalid.
78     if (wholeSubtreeInvalid())
79         return;
80
81     if (other.wholeSubtreeInvalid()) {
82         setWholeSubtreeInvalid();
83         return;
84     }
85
86     if (other.customPseudoInvalid())
87         setCustomPseudoInvalid();
88
89     if (other.treeBoundaryCrossing())
90         setTreeBoundaryCrossing();
91
92     if (other.m_classes) {
93         WillBeHeapHashSet<AtomicString>::const_iterator end = other.m_classes->end();
94         for (WillBeHeapHashSet<AtomicString>::const_iterator it = other.m_classes->begin(); it != end; ++it)
95             addClass(*it);
96     }
97
98     if (other.m_ids) {
99         WillBeHeapHashSet<AtomicString>::const_iterator end = other.m_ids->end();
100         for (WillBeHeapHashSet<AtomicString>::const_iterator it = other.m_ids->begin(); it != end; ++it)
101             addId(*it);
102     }
103
104     if (other.m_tagNames) {
105         WillBeHeapHashSet<AtomicString>::const_iterator end = other.m_tagNames->end();
106         for (WillBeHeapHashSet<AtomicString>::const_iterator it = other.m_tagNames->begin(); it != end; ++it)
107             addTagName(*it);
108     }
109
110     if (other.m_attributes) {
111         WillBeHeapHashSet<AtomicString>::const_iterator end = other.m_attributes->end();
112         for (WillBeHeapHashSet<AtomicString>::const_iterator it = other.m_attributes->begin(); it != end; ++it)
113             addAttribute(*it);
114     }
115 }
116
117 WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureClassSet()
118 {
119     if (!m_classes)
120         m_classes = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>);
121     return *m_classes;
122 }
123
124 WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureIdSet()
125 {
126     if (!m_ids)
127         m_ids = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>);
128     return *m_ids;
129 }
130
131 WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureTagNameSet()
132 {
133     if (!m_tagNames)
134         m_tagNames = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>);
135     return *m_tagNames;
136 }
137
138 WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureAttributeSet()
139 {
140     if (!m_attributes)
141         m_attributes = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>);
142     return *m_attributes;
143 }
144
145 void DescendantInvalidationSet::addClass(const AtomicString& className)
146 {
147     if (wholeSubtreeInvalid())
148         return;
149     ensureClassSet().add(className);
150 }
151
152 void DescendantInvalidationSet::addId(const AtomicString& id)
153 {
154     if (wholeSubtreeInvalid())
155         return;
156     ensureIdSet().add(id);
157 }
158
159 void DescendantInvalidationSet::addTagName(const AtomicString& tagName)
160 {
161     if (wholeSubtreeInvalid())
162         return;
163     ensureTagNameSet().add(tagName);
164 }
165
166 void DescendantInvalidationSet::addAttribute(const AtomicString& attribute)
167 {
168     if (wholeSubtreeInvalid())
169         return;
170     ensureAttributeSet().add(attribute);
171 }
172
173 void DescendantInvalidationSet::setWholeSubtreeInvalid()
174 {
175     if (m_allDescendantsMightBeInvalid)
176         return;
177
178     m_allDescendantsMightBeInvalid = true;
179     m_treeBoundaryCrossing = false;
180     m_classes = nullptr;
181     m_ids = nullptr;
182     m_tagNames = nullptr;
183     m_attributes = nullptr;
184 }
185
186 void DescendantInvalidationSet::trace(Visitor* visitor)
187 {
188 #if ENABLE(OILPAN)
189     visitor->trace(m_classes);
190     visitor->trace(m_ids);
191     visitor->trace(m_tagNames);
192     visitor->trace(m_attributes);
193 #endif
194 }
195
196 #ifndef NDEBUG
197 void DescendantInvalidationSet::show() const
198 {
199     fprintf(stderr, "DescendantInvalidationSet { ");
200     if (m_allDescendantsMightBeInvalid)
201         fprintf(stderr, "* ");
202     if (m_customPseudoInvalid)
203         fprintf(stderr, "::custom ");
204     if (m_treeBoundaryCrossing)
205         fprintf(stderr, "::shadow/deep/ ");
206     if (m_ids) {
207         for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_ids->begin(); it != m_ids->end(); ++it)
208             fprintf(stderr, "#%s ", (*it).ascii().data());
209     }
210     if (m_classes) {
211         for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_classes->begin(); it != m_classes->end(); ++it)
212             fprintf(stderr, ".%s ", (*it).ascii().data());
213     }
214     if (m_tagNames) {
215         for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_tagNames->begin(); it != m_tagNames->end(); ++it)
216             fprintf(stderr, "<%s> ", (*it).ascii().data());
217     }
218     if (m_attributes) {
219         for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_attributes->begin(); it != m_attributes->end(); ++it)
220             fprintf(stderr, "[%s] ", (*it).ascii().data());
221     }
222     fprintf(stderr, "}\n");
223 }
224 #endif // NDEBUG
225
226 } // namespace blink