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 WebCore { 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 } // namespace WebCore 197