Home | History | Annotate | Download | only in invalidation
      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