2 * Copyright (C) 2014 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
32 #include "core/css/invalidation/DescendantInvalidationSet.h"
34 #include "core/css/resolver/StyleResolver.h"
35 #include "core/dom/Element.h"
39 DescendantInvalidationSet::DescendantInvalidationSet()
40 : m_allDescendantsMightBeInvalid(false)
41 , m_customPseudoInvalid(false)
42 , m_treeBoundaryCrossing(false)
46 bool DescendantInvalidationSet::invalidatesElement(Element& element) const
48 if (m_allDescendantsMightBeInvalid)
51 if (m_tagNames && m_tagNames->contains(element.tagQName().localName()))
54 if (element.hasID() && m_ids && m_ids->contains(element.idForStyleResolution()))
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))
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))
75 void DescendantInvalidationSet::combine(const DescendantInvalidationSet& other)
77 // No longer bother combining data structures, since the whole subtree is deemed invalid.
78 if (wholeSubtreeInvalid())
81 if (other.wholeSubtreeInvalid()) {
82 setWholeSubtreeInvalid();
86 if (other.customPseudoInvalid())
87 setCustomPseudoInvalid();
89 if (other.treeBoundaryCrossing())
90 setTreeBoundaryCrossing();
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)
99 WillBeHeapHashSet<AtomicString>::const_iterator end = other.m_ids->end();
100 for (WillBeHeapHashSet<AtomicString>::const_iterator it = other.m_ids->begin(); it != end; ++it)
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)
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)
117 WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureClassSet()
120 m_classes = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>);
124 WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureIdSet()
127 m_ids = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>);
131 WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureTagNameSet()
134 m_tagNames = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>);
138 WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureAttributeSet()
141 m_attributes = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>);
142 return *m_attributes;
145 void DescendantInvalidationSet::addClass(const AtomicString& className)
147 if (wholeSubtreeInvalid())
149 ensureClassSet().add(className);
152 void DescendantInvalidationSet::addId(const AtomicString& id)
154 if (wholeSubtreeInvalid())
156 ensureIdSet().add(id);
159 void DescendantInvalidationSet::addTagName(const AtomicString& tagName)
161 if (wholeSubtreeInvalid())
163 ensureTagNameSet().add(tagName);
166 void DescendantInvalidationSet::addAttribute(const AtomicString& attribute)
168 if (wholeSubtreeInvalid())
170 ensureAttributeSet().add(attribute);
173 void DescendantInvalidationSet::setWholeSubtreeInvalid()
175 if (m_allDescendantsMightBeInvalid)
178 m_allDescendantsMightBeInvalid = true;
179 m_treeBoundaryCrossing = false;
182 m_tagNames = nullptr;
183 m_attributes = nullptr;
186 void DescendantInvalidationSet::trace(Visitor* visitor)
189 visitor->trace(m_classes);
190 visitor->trace(m_ids);
191 visitor->trace(m_tagNames);
192 visitor->trace(m_attributes);
197 void DescendantInvalidationSet::show() const
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/ ");
207 for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_ids->begin(); it != m_ids->end(); ++it)
208 fprintf(stderr, "#%s ", (*it).ascii().data());
211 for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_classes->begin(); it != m_classes->end(); ++it)
212 fprintf(stderr, ".%s ", (*it).ascii().data());
215 for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_tagNames->begin(); it != m_tagNames->end(); ++it)
216 fprintf(stderr, "<%s> ", (*it).ascii().data());
219 for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_attributes->begin(); it != m_attributes->end(); ++it)
220 fprintf(stderr, "[%s] ", (*it).ascii().data());
222 fprintf(stderr, "}\n");