Changeset 154370 in webkit
- Timestamp:
- Aug 20, 2013 3:43:57 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r154365 r154370 1 2013-08-20 Benjamin Poulain <benjamin@webkit.org> 2 3 <https://webkit.org/b/120050> Don't bother using a Vector for the ouput of querySelector, just return the first element found 4 5 Reviewed by Ryosuke Niwa. 6 7 Simplify the case of querySelector. Instead of using the same output type as querySelectorAll, 8 simply use a trait to define what to do in the loop. 9 10 * dom/SelectorQuery.cpp: 11 (WebCore::AllElementExtractorSelectorQueryTrait::appendOutputForElement): 12 (WebCore::SelectorDataList::queryAll): 13 (WebCore::SingleElementExtractorSelectorQueryTrait::appendOutputForElement): 14 (WebCore::SelectorDataList::queryFirst): 15 (WebCore::SelectorDataList::executeFastPathForIdSelector): 16 (WebCore::elementsForLocalName): 17 (WebCore::anyElement): 18 (WebCore::SelectorDataList::executeSingleTagNameSelectorData): 19 (WebCore::SelectorDataList::executeSingleClassNameSelectorData): 20 (WebCore::SelectorDataList::executeSingleSelectorData): 21 (WebCore::SelectorDataList::executeSingleMultiSelectorData): 22 (WebCore::SelectorDataList::execute): 23 * dom/SelectorQuery.h: 24 1 25 2013-08-20 Antti Koivisto <antti@apple.com> 2 26 -
trunk/Source/WebCore/dom/SelectorQuery.cpp
r154037 r154370 81 81 } 82 82 83 struct AllElementExtractorSelectorQueryTrait { 84 typedef Vector<RefPtr<Node>> OutputType; 85 static const bool shouldOnlyMatchFirstElement = false; 86 static void appendOutputForElement(OutputType& output, Element* element) { output.append(element); } 87 }; 88 83 89 PassRefPtr<NodeList> SelectorDataList::queryAll(Node* rootNode) const 84 90 { 85 Vector<RefPtr<Node> 86 execute< false>(rootNode, result);91 Vector<RefPtr<Node>> result; 92 execute<AllElementExtractorSelectorQueryTrait>(rootNode, result); 87 93 return StaticNodeList::adopt(result); 88 94 } 89 95 96 struct SingleElementExtractorSelectorQueryTrait { 97 typedef Element* OutputType; 98 static const bool shouldOnlyMatchFirstElement = true; 99 static void appendOutputForElement(OutputType& output, Element* element) 100 { 101 ASSERT(element); 102 ASSERT(!output); 103 output = element; 104 } 105 }; 106 90 107 PassRefPtr<Element> SelectorDataList::queryFirst(Node* rootNode) const 91 108 { 92 Vector<RefPtr<Node> > result; 93 execute<true>(rootNode, result); 94 if (result.isEmpty()) 95 return 0; 96 ASSERT(result.size() == 1); 97 ASSERT(result.first()->isElementNode()); 98 return toElement(result.first().get()); 109 Element* result = 0; 110 execute<SingleElementExtractorSelectorQueryTrait>(rootNode, result); 111 return result; 99 112 } 100 113 … … 123 136 } 124 137 125 template < bool firstMatchOnly>126 ALWAYS_INLINE void SelectorDataList::executeFastPathForIdSelector(const Node* rootNode, const SelectorData& selectorData, const CSSSelector* idSelector, Vector<RefPtr<Node> >& matchedElements) const138 template <typename SelectorQueryTrait> 139 ALWAYS_INLINE void SelectorDataList::executeFastPathForIdSelector(const Node* rootNode, const SelectorData& selectorData, const CSSSelector* idSelector, typename SelectorQueryTrait::OutputType& output) const 127 140 { 128 141 ASSERT(m_selectors.size() == 1); 129 142 ASSERT(idSelector); 143 130 144 const AtomicString& idToMatch = idSelector->value(); 131 145 if (UNLIKELY(rootNode->treeScope()->containsMultipleElementsWithId(idToMatch))) { … … 137 151 Element* element = elements->at(i); 138 152 if ((rootNodeIsTreeScopeRoot || element->isDescendantOf(rootNode)) && selectorMatches(selectorData, element, rootNode)) { 139 matchedElements.append(element);140 if ( firstMatchOnly)153 SelectorQueryTrait::appendOutputForElement(output, element); 154 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) 141 155 return; 142 156 } … … 144 158 return; 145 159 } 160 146 161 Element* element = rootNode->treeScope()->getElementById(idToMatch); 147 162 if (!element || !(isTreeScopeRoot(rootNode) || element->isDescendantOf(rootNode))) 148 163 return; 149 164 if (selectorMatches(selectorData, element, rootNode)) 150 matchedElements.append(element);165 SelectorQueryTrait::appendOutputForElement(output, element); 151 166 } 152 167 … … 156 171 } 157 172 158 template < bool firstMatchOnly>159 static inline void elementsForLocalName(const Node* rootNode, const AtomicString& localName, Vector<RefPtr<Node> >& matchedElements)160 { 161 for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) { 162 if (element-> localName() == localName) {163 matchedElements.append(element);164 if ( firstMatchOnly)173 template <typename SelectorQueryTrait> 174 static inline void elementsForLocalName(const Node* rootNode, const AtomicString& localName, typename SelectorQueryTrait::OutputType& output) 175 { 176 for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) { 177 if (element->tagQName().localName() == localName) { 178 SelectorQueryTrait::appendOutputForElement(output, element); 179 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) 165 180 return; 166 181 } … … 168 183 } 169 184 170 template < bool firstMatchOnly>171 static inline void anyElement(const Node* rootNode, Vector<RefPtr<Node> >& matchedElements)172 { 173 for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) { 174 matchedElements.append(element);175 if ( firstMatchOnly)185 template <typename SelectorQueryTrait> 186 static inline void anyElement(const Node* rootNode, typename SelectorQueryTrait::OutputType& output) 187 { 188 for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) { 189 SelectorQueryTrait::appendOutputForElement(output, element); 190 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) 176 191 return; 177 192 } … … 179 194 180 195 181 template < bool firstMatchOnly>182 ALWAYS_INLINE void SelectorDataList::executeSingleTagNameSelectorData(const Node* rootNode, const SelectorData& selectorData, Vector<RefPtr<Node> >& matchedElements) const196 template <typename SelectorQueryTrait> 197 ALWAYS_INLINE void SelectorDataList::executeSingleTagNameSelectorData(const Node* rootNode, const SelectorData& selectorData, typename SelectorQueryTrait::OutputType& output) const 183 198 { 184 199 ASSERT(m_selectors.size() == 1); … … 192 207 if (selectorLocalName != starAtom) { 193 208 // Common case: name defined, selectorNamespaceURI is a wildcard. 194 elementsForLocalName< firstMatchOnly>(rootNode, selectorLocalName, matchedElements);209 elementsForLocalName<SelectorQueryTrait>(rootNode, selectorLocalName, output); 195 210 } else { 196 211 // Other fairly common case: both are wildcards. 197 anyElement< firstMatchOnly>(rootNode, matchedElements);212 anyElement<SelectorQueryTrait>(rootNode, output); 198 213 } 199 214 } else { 200 215 // Fallback: NamespaceURI is set, selectorLocalName may be starAtom. 201 216 for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) { 202 if (element->namespaceURI() == selectorNamespaceURI && (selectorLocalName == starAtom || element-> localName() == selectorLocalName)) {203 matchedElements.append(element);204 if ( firstMatchOnly)205 break;217 if (element->namespaceURI() == selectorNamespaceURI && (selectorLocalName == starAtom || element->tagQName().localName() == selectorLocalName)) { 218 SelectorQueryTrait::appendOutputForElement(output, element); 219 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) 220 return; 206 221 } 207 222 } 208 223 } 209 #if !ASSERT_DISABLED210 for (size_t i = 0; i < matchedElements.size(); ++i) {211 ASSERT(matchedElements[i]->isElementNode());212 ASSERT(SelectorChecker::tagMatches(static_cast<const Element*>(matchedElements[i].get()), tagQualifiedName));213 }214 #endif215 224 } 216 225 … … 220 229 } 221 230 222 template < bool firstMatchOnly>223 ALWAYS_INLINE void SelectorDataList::executeSingleClassNameSelectorData(const Node* rootNode, const SelectorData& selectorData, Vector<RefPtr<Node> >& matchedElements) const231 template <typename SelectorQueryTrait> 232 ALWAYS_INLINE void SelectorDataList::executeSingleClassNameSelectorData(const Node* rootNode, const SelectorData& selectorData, typename SelectorQueryTrait::OutputType& output) const 224 233 { 225 234 ASSERT(m_selectors.size() == 1); … … 229 238 for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) { 230 239 if (element->hasClass() && element->classNames().contains(className)) { 231 matchedElements.append(element);232 if ( firstMatchOnly)240 SelectorQueryTrait::appendOutputForElement(output, element); 241 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) 233 242 return; 234 243 } … … 236 245 } 237 246 238 template < bool firstMatchOnly>239 ALWAYS_INLINE void SelectorDataList::executeSingleSelectorData(const Node* rootNode, const SelectorData& selectorData, Vector<RefPtr<Node> >& matchedElements) const247 template <typename SelectorQueryTrait> 248 ALWAYS_INLINE void SelectorDataList::executeSingleSelectorData(const Node* rootNode, const SelectorData& selectorData, typename SelectorQueryTrait::OutputType& output) const 240 249 { 241 250 ASSERT(m_selectors.size() == 1); … … 243 252 for (Element* element = ElementTraversal::firstWithin(rootNode); element; element = ElementTraversal::next(element, rootNode)) { 244 253 if (selectorMatches(selectorData, element, rootNode)) { 245 matchedElements.append(element);246 if ( firstMatchOnly)254 SelectorQueryTrait::appendOutputForElement(output, element); 255 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) 247 256 return; 248 257 } … … 250 259 } 251 260 252 template < bool firstMatchOnly>253 ALWAYS_INLINE void SelectorDataList::executeSingleMultiSelectorData(const Node* rootNode, Vector<RefPtr<Node> >& matchedElements) const261 template <typename SelectorQueryTrait> 262 ALWAYS_INLINE void SelectorDataList::executeSingleMultiSelectorData(const Node* rootNode, typename SelectorQueryTrait::OutputType& output) const 254 263 { 255 264 unsigned selectorCount = m_selectors.size(); … … 257 266 for (unsigned i = 0; i < selectorCount; ++i) { 258 267 if (selectorMatches(m_selectors[i], element, rootNode)) { 259 matchedElements.append(element);260 if ( firstMatchOnly)268 SelectorQueryTrait::appendOutputForElement(output, element); 269 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) 261 270 return; 262 271 break; … … 266 275 } 267 276 268 template < bool firstMatchOnly>269 ALWAYS_INLINE void SelectorDataList::execute(Node* rootNode, Vector<RefPtr<Node> >& matchedElements) const277 template <typename SelectorQueryTrait> 278 ALWAYS_INLINE void SelectorDataList::execute(Node* rootNode, typename SelectorQueryTrait::OutputType& output) const 270 279 { 271 280 if (m_selectors.size() == 1) { 272 281 const SelectorData& selectorData = m_selectors[0]; 273 282 if (const CSSSelector* idSelector = selectorForIdLookup(rootNode, selectorData.selector)) 274 executeFastPathForIdSelector< firstMatchOnly>(rootNode, selectorData, idSelector, matchedElements);283 executeFastPathForIdSelector<SelectorQueryTrait>(rootNode, selectorData, idSelector, output); 275 284 else if (isSingleTagNameSelector(selectorData.selector)) 276 executeSingleTagNameSelectorData< firstMatchOnly>(rootNode, selectorData, matchedElements);285 executeSingleTagNameSelectorData<SelectorQueryTrait>(rootNode, selectorData, output); 277 286 else if (isSingleClassNameSelector(selectorData.selector)) 278 executeSingleClassNameSelectorData< firstMatchOnly>(rootNode, selectorData, matchedElements);287 executeSingleClassNameSelectorData<SelectorQueryTrait>(rootNode, selectorData, output); 279 288 else 280 executeSingleSelectorData< firstMatchOnly>(rootNode, selectorData, matchedElements);289 executeSingleSelectorData<SelectorQueryTrait>(rootNode, selectorData, output); 281 290 return; 282 291 } 283 executeSingleMultiSelectorData< firstMatchOnly>(rootNode, matchedElements);292 executeSingleMultiSelectorData<SelectorQueryTrait>(rootNode, output); 284 293 } 285 294 -
trunk/Source/WebCore/dom/SelectorQuery.h
r151365 r154370 59 59 60 60 bool selectorMatches(const SelectorData&, Element*, const Node*) const; 61 template <bool firstMatchOnly>62 void execute(Node* rootNode, Vector<RefPtr<Node> >&) const;63 61 64 template <bool firstMatchOnly> void executeFastPathForIdSelector(const Node* rootNode, const SelectorData&, const CSSSelector* idSelector, Vector<RefPtr<Node> >&) const; 65 template <bool firstMatchOnly> void executeSingleTagNameSelectorData(const Node* rootNode, const SelectorData&, Vector<RefPtr<Node> >&) const; 66 template <bool firstMatchOnly> void executeSingleClassNameSelectorData(const Node* rootNode, const SelectorData&, Vector<RefPtr<Node> >&) const; 67 template <bool firstMatchOnly> void executeSingleSelectorData(const Node* rootNode, const SelectorData&, Vector<RefPtr<Node> >&) const; 68 template <bool firstMatchOnly> void executeSingleMultiSelectorData(const Node* rootNode, Vector<RefPtr<Node> >&) const; 62 template <typename SelectorQueryTrait> void execute(Node* rootNode, typename SelectorQueryTrait::OutputType&) const; 63 template <typename SelectorQueryTrait> void executeFastPathForIdSelector(const Node* rootNode, const SelectorData&, const CSSSelector* idSelector, typename SelectorQueryTrait::OutputType&) const; 64 template <typename SelectorQueryTrait> void executeSingleTagNameSelectorData(const Node* rootNode, const SelectorData&, typename SelectorQueryTrait::OutputType&) const; 65 template <typename SelectorQueryTrait> void executeSingleClassNameSelectorData(const Node* rootNode, const SelectorData&, typename SelectorQueryTrait::OutputType&) const; 66 template <typename SelectorQueryTrait> void executeSingleSelectorData(const Node* rootNode, const SelectorData&, typename SelectorQueryTrait::OutputType&) const; 67 template <typename SelectorQueryTrait> void executeSingleMultiSelectorData(const Node* rootNode, typename SelectorQueryTrait::OutputType&) const; 69 68 70 69 Vector<SelectorData> m_selectors;
Note: See TracChangeset
for help on using the changeset viewer.