• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
3  * Copyright (C) 2009 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "config.h"
28 #include "core/css/CSSSelectorList.h"
29 
30 #include "core/css/CSSParserValues.h"
31 #include "wtf/text/StringBuilder.h"
32 
33 namespace WebCore {
34 
~CSSSelectorList()35 CSSSelectorList::~CSSSelectorList()
36 {
37     deleteSelectors();
38 }
39 
CSSSelectorList(const CSSSelectorList & other)40 CSSSelectorList::CSSSelectorList(const CSSSelectorList& other)
41 {
42     unsigned otherLength = other.length();
43     m_selectorArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * otherLength));
44     for (unsigned i = 0; i < otherLength; ++i)
45         new (&m_selectorArray[i]) CSSSelector(other.m_selectorArray[i]);
46 }
47 
adopt(CSSSelectorList & list)48 void CSSSelectorList::adopt(CSSSelectorList& list)
49 {
50     deleteSelectors();
51     m_selectorArray = list.m_selectorArray;
52     list.m_selectorArray = 0;
53 }
54 
adoptSelectorVector(Vector<OwnPtr<CSSParserSelector>> & selectorVector)55 void CSSSelectorList::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
56 {
57     deleteSelectors();
58     size_t flattenedSize = 0;
59     for (size_t i = 0; i < selectorVector.size(); ++i) {
60         for (CSSParserSelector* selector = selectorVector[i].get(); selector; selector = selector->tagHistory())
61             ++flattenedSize;
62     }
63     ASSERT(flattenedSize);
64     m_selectorArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * flattenedSize));
65     size_t arrayIndex = 0;
66     for (size_t i = 0; i < selectorVector.size(); ++i) {
67         CSSParserSelector* current = selectorVector[i].get();
68         while (current) {
69             // Move item from the parser selector vector into m_selectorArray without invoking destructor (Ugh.)
70             CSSSelector* currentSelector = current->releaseSelector().leakPtr();
71             memcpy(&m_selectorArray[arrayIndex], currentSelector, sizeof(CSSSelector));
72             fastFree(currentSelector);
73 
74             current = current->tagHistory();
75             ASSERT(!m_selectorArray[arrayIndex].isLastInSelectorList());
76             if (current)
77                 m_selectorArray[arrayIndex].setNotLastInTagHistory();
78             ++arrayIndex;
79         }
80         ASSERT(m_selectorArray[arrayIndex - 1].isLastInTagHistory());
81     }
82     ASSERT(flattenedSize == arrayIndex);
83     m_selectorArray[arrayIndex - 1].setLastInSelectorList();
84     selectorVector.clear();
85 }
86 
length() const87 unsigned CSSSelectorList::length() const
88 {
89     if (!m_selectorArray)
90         return 0;
91     CSSSelector* current = m_selectorArray;
92     while (!current->isLastInSelectorList())
93         ++current;
94     return (current - m_selectorArray) + 1;
95 }
96 
deleteSelectors()97 void CSSSelectorList::deleteSelectors()
98 {
99     if (!m_selectorArray)
100         return;
101 
102     bool finished = false;
103     for (CSSSelector* s = m_selectorArray; !finished; ++s) {
104         finished = s->isLastInSelectorList();
105         s->~CSSSelector();
106     }
107 
108     fastFree(m_selectorArray);
109 }
110 
selectorsText() const111 String CSSSelectorList::selectorsText() const
112 {
113     StringBuilder result;
114 
115     for (const CSSSelector* s = first(); s; s = next(s)) {
116         if (s != first())
117             result.append(", ");
118         result.append(s->selectorText());
119     }
120 
121     return result.toString();
122 }
123 
124 template <typename Functor>
forEachTagSelector(Functor & functor,const CSSSelector * selector)125 static bool forEachTagSelector(Functor& functor, const CSSSelector* selector)
126 {
127     ASSERT(selector);
128 
129     do {
130         if (functor(selector))
131             return true;
132         if (const CSSSelectorList* selectorList = selector->selectorList()) {
133             for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
134                 if (forEachTagSelector(functor, subSelector))
135                     return true;
136             }
137         }
138     } while ((selector = selector->tagHistory()));
139 
140     return false;
141 }
142 
143 template <typename Functor>
forEachSelector(Functor & functor,const CSSSelectorList * selectorList)144 static bool forEachSelector(Functor& functor, const CSSSelectorList* selectorList)
145 {
146     for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) {
147         if (forEachTagSelector(functor, selector))
148             return true;
149     }
150 
151     return false;
152 }
153 
154 class SelectorNeedsNamespaceResolutionFunctor {
155 public:
operator ()(const CSSSelector * selector)156     bool operator()(const CSSSelector* selector)
157     {
158         if (selector->m_match == CSSSelector::Tag && selector->tagQName().prefix() != nullAtom && selector->tagQName().prefix() != starAtom)
159             return true;
160         if (selector->isAttributeSelector() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom)
161             return true;
162         return false;
163     }
164 };
165 
selectorsNeedNamespaceResolution()166 bool CSSSelectorList::selectorsNeedNamespaceResolution()
167 {
168     SelectorNeedsNamespaceResolutionFunctor functor;
169     return forEachSelector(functor, this);
170 }
171 
172 class SelectorHasShadowDistributed {
173 public:
operator ()(const CSSSelector * selector)174     bool operator()(const CSSSelector* selector)
175     {
176         return selector->relationIsAffectedByPseudoContent();
177     }
178 };
179 
hasShadowDistributedAt(size_t index) const180 bool CSSSelectorList::hasShadowDistributedAt(size_t index) const
181 {
182     SelectorHasShadowDistributed functor;
183     return forEachTagSelector(functor, selectorAt(index));
184 }
185 
186 class SelectorHasCombinatorCrossingTreeBoundary {
187 public:
operator ()(const CSSSelector * selector)188     bool operator()(const CSSSelector* selector)
189     {
190         return selector->relation() == CSSSelector::ChildTree || selector->relation() == CSSSelector::DescendantTree;
191     }
192 };
193 
hasCombinatorCrossingTreeBoundaryAt(size_t index) const194 bool CSSSelectorList::hasCombinatorCrossingTreeBoundaryAt(size_t index) const
195 {
196     SelectorHasCombinatorCrossingTreeBoundary functor;
197     return forEachTagSelector(functor, selectorAt(index));
198 }
199 
200 } // namespace WebCore
201