OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 | 132 |
133 unsigned selectorCount = 0; | 133 unsigned selectorCount = 0; |
134 for (const CSSSelector* selector = selectorList.first(); selector; selector
= CSSSelectorList::next(selector)) | 134 for (const CSSSelector* selector = selectorList.first(); selector; selector
= CSSSelectorList::next(selector)) |
135 selectorCount++; | 135 selectorCount++; |
136 | 136 |
137 m_selectors.reserveInitialCapacity(selectorCount); | 137 m_selectors.reserveInitialCapacity(selectorCount); |
138 for (const CSSSelector* selector = selectorList.first(); selector; selector
= CSSSelectorList::next(selector)) | 138 for (const CSSSelector* selector = selectorList.first(); selector; selector
= CSSSelectorList::next(selector)) |
139 m_selectors.uncheckedAppend(SelectorData(selector, SelectorCheckerFastPa
th::canUse(selector))); | 139 m_selectors.uncheckedAppend(SelectorData(selector, SelectorCheckerFastPa
th::canUse(selector))); |
140 } | 140 } |
141 | 141 |
142 inline bool SelectorDataList::selectorMatches(const SelectorData& selectorData,
Element* element, const Node* rootNode) const | 142 inline bool SelectorDataList::selectorMatches(const SelectorData& selectorData,
Element& element, const Node& rootNode) const |
143 { | 143 { |
144 if (selectorData.isFastCheckable && !element->isSVGElement()) { | 144 if (selectorData.isFastCheckable && !element.isSVGElement()) { |
145 SelectorCheckerFastPath selectorCheckerFastPath(selectorData.selector, e
lement); | 145 SelectorCheckerFastPath selectorCheckerFastPath(selectorData.selector, e
lement); |
146 if (!selectorCheckerFastPath.matchesRightmostSelector(SelectorChecker::V
isitedMatchDisabled)) | 146 if (!selectorCheckerFastPath.matchesRightmostSelector(SelectorChecker::V
isitedMatchDisabled)) |
147 return false; | 147 return false; |
148 return selectorCheckerFastPath.matches(); | 148 return selectorCheckerFastPath.matches(); |
149 } | 149 } |
150 | 150 |
151 SelectorChecker selectorChecker(element->document(), SelectorChecker::Queryi
ngRules); | 151 SelectorChecker selectorChecker(element.document(), SelectorChecker::Queryin
gRules); |
152 SelectorChecker::SelectorCheckingContext selectorCheckingContext(selectorDat
a.selector, element, SelectorChecker::VisitedMatchDisabled); | 152 SelectorChecker::SelectorCheckingContext selectorCheckingContext(selectorDat
a.selector, &element, SelectorChecker::VisitedMatchDisabled); |
153 selectorCheckingContext.behaviorAtBoundary = SelectorChecker::StaysWithinTre
eScope; | 153 selectorCheckingContext.behaviorAtBoundary = SelectorChecker::StaysWithinTre
eScope; |
154 selectorCheckingContext.scope = !rootNode->isDocumentNode() && rootNode->isC
ontainerNode() ? toContainerNode(rootNode) : 0; | 154 selectorCheckingContext.scope = !rootNode.isDocumentNode() && rootNode.isCon
tainerNode() ? &toContainerNode(rootNode) : 0; |
155 PseudoId ignoreDynamicPseudo = NOPSEUDO; | 155 PseudoId ignoreDynamicPseudo = NOPSEUDO; |
156 return selectorChecker.match(selectorCheckingContext, ignoreDynamicPseudo, D
OMSiblingTraversalStrategy()) == SelectorChecker::SelectorMatches; | 156 return selectorChecker.match(selectorCheckingContext, ignoreDynamicPseudo, D
OMSiblingTraversalStrategy()) == SelectorChecker::SelectorMatches; |
157 } | 157 } |
158 | 158 |
159 bool SelectorDataList::matches(Element* targetElement) const | 159 bool SelectorDataList::matches(Element& targetElement) const |
160 { | 160 { |
161 ASSERT(targetElement); | |
162 | |
163 unsigned selectorCount = m_selectors.size(); | 161 unsigned selectorCount = m_selectors.size(); |
164 for (unsigned i = 0; i < selectorCount; ++i) { | 162 for (unsigned i = 0; i < selectorCount; ++i) { |
165 if (selectorMatches(m_selectors[i], targetElement, targetElement)) | 163 if (selectorMatches(m_selectors[i], targetElement, targetElement)) |
166 return true; | 164 return true; |
167 } | 165 } |
168 | 166 |
169 return false; | 167 return false; |
170 } | 168 } |
171 | 169 |
172 PassRefPtr<NodeList> SelectorDataList::queryAll(Node* rootNode) const | 170 PassRefPtr<NodeList> SelectorDataList::queryAll(Node& rootNode) const |
173 { | 171 { |
174 Vector<RefPtr<Node> > result; | 172 Vector<RefPtr<Node> > result; |
175 executeQueryAll(rootNode, result); | 173 executeQueryAll(rootNode, result); |
176 return StaticNodeList::adopt(result); | 174 return StaticNodeList::adopt(result); |
177 } | 175 } |
178 | 176 |
179 PassRefPtr<Element> SelectorDataList::queryFirst(Node* rootNode) const | 177 PassRefPtr<Element> SelectorDataList::queryFirst(Node& rootNode) const |
180 { | 178 { |
181 return executeQueryFirst(rootNode); | 179 return executeQueryFirst(rootNode); |
182 } | 180 } |
183 | 181 |
184 static inline bool isTreeScopeRoot(Node* node) | 182 static inline bool isTreeScopeRoot(Node* node) |
185 { | 183 { |
186 ASSERT(node); | 184 ASSERT(node); |
187 return node->isDocumentNode() || node->isShadowRoot(); | 185 return node->isDocumentNode() || node->isShadowRoot(); |
188 } | 186 } |
189 | 187 |
190 void SelectorDataList::collectElementsByClassName(Node* rootNode, const AtomicSt
ring& className, Vector<RefPtr<Node> >& traversalRoots) const | 188 void SelectorDataList::collectElementsByClassName(Node& rootNode, const AtomicSt
ring& className, Vector<RefPtr<Node> >& traversalRoots) const |
191 { | 189 { |
192 for (Element* element = ElementTraversal::firstWithin(rootNode); element; el
ement = ElementTraversal::next(element, rootNode)) { | 190 for (Element* element = ElementTraversal::firstWithin(&rootNode); element; e
lement = ElementTraversal::next(element, &rootNode)) { |
193 if (element->hasClass() && element->classNames().contains(className)) | 191 if (element->hasClass() && element->classNames().contains(className)) |
194 traversalRoots.append(element); | 192 traversalRoots.append(element); |
195 } | 193 } |
196 } | 194 } |
197 | 195 |
198 void SelectorDataList::collectElementsByTagName(Node* rootNode, const QualifiedN
ame& tagName, Vector<RefPtr<Node> >& traversalRoots) const | 196 void SelectorDataList::collectElementsByTagName(Node& rootNode, const QualifiedN
ame& tagName, Vector<RefPtr<Node> >& traversalRoots) const |
199 { | 197 { |
200 for (Element* element = ElementTraversal::firstWithin(rootNode); element; el
ement = ElementTraversal::next(element, rootNode)) { | 198 for (Element* element = ElementTraversal::firstWithin(&rootNode); element; e
lement = ElementTraversal::next(element, &rootNode)) { |
201 if (SelectorChecker::tagMatches(element, tagName)) | 199 if (SelectorChecker::tagMatches(*element, tagName)) |
202 traversalRoots.append(element); | 200 traversalRoots.append(element); |
203 } | 201 } |
204 } | 202 } |
205 | 203 |
206 Element* SelectorDataList::findElementByClassName(Node* rootNode, const AtomicSt
ring& className) const | 204 Element* SelectorDataList::findElementByClassName(Node& rootNode, const AtomicSt
ring& className) const |
207 { | 205 { |
208 for (Element* element = ElementTraversal::firstWithin(rootNode); element; el
ement = ElementTraversal::next(element, rootNode)) { | 206 for (Element* element = ElementTraversal::firstWithin(&rootNode); element; e
lement = ElementTraversal::next(element, &rootNode)) { |
209 if (element->hasClass() && element->classNames().contains(className)) | 207 if (element->hasClass() && element->classNames().contains(className)) |
210 return element; | 208 return element; |
211 } | 209 } |
212 return 0; | 210 return 0; |
213 } | 211 } |
214 | 212 |
215 Element* SelectorDataList::findElementByTagName(Node* rootNode, const QualifiedN
ame& tagName) const | 213 Element* SelectorDataList::findElementByTagName(Node& rootNode, const QualifiedN
ame& tagName) const |
216 { | 214 { |
217 for (Element* element = ElementTraversal::firstWithin(rootNode); element; el
ement = ElementTraversal::next(element, rootNode)) { | 215 for (Element* element = ElementTraversal::firstWithin(&rootNode); element; e
lement = ElementTraversal::next(element, &rootNode)) { |
218 if (SelectorChecker::tagMatches(element, tagName)) | 216 if (SelectorChecker::tagMatches(*element, tagName)) |
219 return element; | 217 return element; |
220 } | 218 } |
221 return 0; | 219 return 0; |
222 } | 220 } |
223 | 221 |
224 inline bool SelectorDataList::canUseFastQuery(Node* rootNode) const | 222 inline bool SelectorDataList::canUseFastQuery(const Node& rootNode) const |
225 { | 223 { |
226 return m_selectors.size() == 1 && rootNode->inDocument() && !rootNode->docum
ent().inQuirksMode(); | 224 return m_selectors.size() == 1 && rootNode.inDocument() && !rootNode.documen
t().inQuirksMode(); |
227 } | 225 } |
228 | 226 |
229 inline bool ancestorHasClassName(Node* rootNode, const AtomicString& className) | 227 inline bool ancestorHasClassName(Node* rootNode, const AtomicString& className) |
230 { | 228 { |
231 if (!rootNode->isElementNode()) | 229 if (!rootNode->isElementNode()) |
232 return false; | 230 return false; |
233 | 231 |
234 for (Element* element = toElement(rootNode); element; element = element->par
entElement()) { | 232 for (Element* element = toElement(rootNode); element; element = element->par
entElement()) { |
235 if (element->hasClass() && element->classNames().contains(className)) | 233 if (element->hasClass() && element->classNames().contains(className)) |
236 return true; | 234 return true; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 if (selector->relation() == CSSSelector::DirectAdjacent || selector->rel
ation() == CSSSelector::IndirectAdjacent) | 294 if (selector->relation() == CSSSelector::DirectAdjacent || selector->rel
ation() == CSSSelector::IndirectAdjacent) |
297 startFromParent = true; | 295 startFromParent = true; |
298 else | 296 else |
299 startFromParent = false; | 297 startFromParent = false; |
300 } | 298 } |
301 | 299 |
302 matchTraverseRoots = false; | 300 matchTraverseRoots = false; |
303 return adoptPtr(new SingleNodeList(rootNode)); | 301 return adoptPtr(new SingleNodeList(rootNode)); |
304 } | 302 } |
305 | 303 |
306 void SelectorDataList::executeSlowQueryAll(Node* rootNode, Vector<RefPtr<Node> >
& matchedElements) const | 304 void SelectorDataList::executeSlowQueryAll(Node& rootNode, Vector<RefPtr<Node> >
& matchedElements) const |
307 { | 305 { |
308 for (Element* element = ElementTraversal::firstWithin(rootNode); element; el
ement = ElementTraversal::next(element, rootNode)) { | 306 for (Element* element = ElementTraversal::firstWithin(&rootNode); element; e
lement = ElementTraversal::next(element, &rootNode)) { |
309 for (unsigned i = 0; i < m_selectors.size(); ++i) { | 307 for (unsigned i = 0; i < m_selectors.size(); ++i) { |
310 if (selectorMatches(m_selectors[i], element, rootNode)) { | 308 if (selectorMatches(m_selectors[i], *element, rootNode)) { |
311 matchedElements.append(element); | 309 matchedElements.append(element); |
312 break; | 310 break; |
313 } | 311 } |
314 } | 312 } |
315 } | 313 } |
316 } | 314 } |
317 | 315 |
318 void SelectorDataList::executeQueryAll(Node* rootNode, Vector<RefPtr<Node> >& ma
tchedElements) const | 316 void SelectorDataList::executeQueryAll(Node& rootNode, Vector<RefPtr<Node> >& ma
tchedElements) const |
319 { | 317 { |
320 if (!canUseFastQuery(rootNode)) | 318 if (!canUseFastQuery(rootNode)) |
321 return executeSlowQueryAll(rootNode, matchedElements); | 319 return executeSlowQueryAll(rootNode, matchedElements); |
322 | 320 |
323 ASSERT(m_selectors.size() == 1); | 321 ASSERT(m_selectors.size() == 1); |
324 ASSERT(m_selectors[0].selector); | 322 ASSERT(m_selectors[0].selector); |
325 | 323 |
326 const CSSSelector* firstSelector = m_selectors[0].selector; | 324 const CSSSelector* firstSelector = m_selectors[0].selector; |
327 | 325 |
328 if (!firstSelector->tagHistory()) { | 326 if (!firstSelector->tagHistory()) { |
329 // Fast path for querySelectorAll('#id'), querySelectorAl('.foo'), and q
uerySelectorAll('div'). | 327 // Fast path for querySelectorAll('#id'), querySelectorAl('.foo'), and q
uerySelectorAll('div'). |
330 switch (firstSelector->m_match) { | 328 switch (firstSelector->m_match) { |
331 case CSSSelector::Id: | 329 case CSSSelector::Id: |
332 { | 330 { |
333 if (rootNode->document().containsMultipleElementsWithId(firstSel
ector->value())) | 331 if (rootNode.document().containsMultipleElementsWithId(firstSele
ctor->value())) |
334 break; | 332 break; |
335 | 333 |
336 // Just the same as getElementById. | 334 // Just the same as getElementById. |
337 Element* element = rootNode->treeScope().getElementById(firstSel
ector->value()); | 335 Element* element = rootNode.treeScope().getElementById(firstSele
ctor->value()); |
338 if (element && (isTreeScopeRoot(rootNode) || element->isDescenda
ntOf(rootNode))) | 336 if (element && (isTreeScopeRoot(rootNode) || element->isDescenda
ntOf(&rootNode))) |
339 matchedElements.append(element); | 337 matchedElements.append(element); |
340 return; | 338 return; |
341 } | 339 } |
342 case CSSSelector::Class: | 340 case CSSSelector::Class: |
343 return collectElementsByClassName(rootNode, firstSelector->value(),
matchedElements); | 341 return collectElementsByClassName(rootNode, firstSelector->value(),
matchedElements); |
344 case CSSSelector::Tag: | 342 case CSSSelector::Tag: |
345 return collectElementsByTagName(rootNode, firstSelector->tagQName(),
matchedElements); | 343 return collectElementsByTagName(rootNode, firstSelector->tagQName(),
matchedElements); |
346 default: | 344 default: |
347 break; // If we need another fast path, add here. | 345 break; // If we need another fast path, add here. |
348 } | 346 } |
349 } | 347 } |
350 | 348 |
351 bool matchTraverseRoots; | 349 bool matchTraverseRoots; |
352 OwnPtr<SimpleNodeList> traverseRoots = findTraverseRoots(rootNode, matchTrav
erseRoots); | 350 OwnPtr<SimpleNodeList> traverseRoots = findTraverseRoots(&rootNode, matchTra
verseRoots); |
353 if (traverseRoots->isEmpty()) | 351 if (traverseRoots->isEmpty()) |
354 return; | 352 return; |
355 | 353 |
356 const SelectorData& selector = m_selectors[0]; | 354 const SelectorData& selector = m_selectors[0]; |
357 if (matchTraverseRoots) { | 355 if (matchTraverseRoots) { |
358 while (!traverseRoots->isEmpty()) { | 356 while (!traverseRoots->isEmpty()) { |
359 Node* node = traverseRoots->next(); | 357 Node& node = *traverseRoots->next(); |
360 Element* element = toElement(node); | 358 Element& element = toElement(node); |
361 if (selectorMatches(selector, element, rootNode)) | 359 if (selectorMatches(selector, element, rootNode)) |
362 matchedElements.append(element); | 360 matchedElements.append(&element); |
363 } | 361 } |
364 return; | 362 return; |
365 } | 363 } |
366 | 364 |
367 while (!traverseRoots->isEmpty()) { | 365 while (!traverseRoots->isEmpty()) { |
368 Node* traverseRoot = traverseRoots->next(); | 366 Node* traverseRoot = traverseRoots->next(); |
369 for (Element* element = ElementTraversal::firstWithin(traverseRoot); ele
ment; element = ElementTraversal::next(element, traverseRoot)) { | 367 for (Element* element = ElementTraversal::firstWithin(traverseRoot); ele
ment; element = ElementTraversal::next(element, traverseRoot)) { |
370 if (selectorMatches(selector, element, rootNode)) | 368 if (selectorMatches(selector, *element, rootNode)) |
371 matchedElements.append(element); | 369 matchedElements.append(element); |
372 } | 370 } |
373 } | 371 } |
374 } | 372 } |
375 | 373 |
376 // If matchTraverseRoot is true, the returned Node is the single Element that ma
y match the selector query. | 374 // If matchTraverseRoot is true, the returned Node is the single Element that ma
y match the selector query. |
377 // | 375 // |
378 // If matchTraverseRoot is false, the returned Node is the rootNode parameter or
a descendant of rootNode representing | 376 // If matchTraverseRoot is false, the returned Node is the rootNode parameter or
a descendant of rootNode representing |
379 // the subtree for which we can limit the querySelector traversal. | 377 // the subtree for which we can limit the querySelector traversal. |
380 // | 378 // |
381 // The returned Node may be 0, regardless of matchTraverseRoot, if this method f
inds that the selectors won't | 379 // The returned Node may be 0, regardless of matchTraverseRoot, if this method f
inds that the selectors won't |
382 // match any element. | 380 // match any element. |
383 Node* SelectorDataList::findTraverseRoot(Node* rootNode, bool& matchTraverseRoot
) const | 381 Node* SelectorDataList::findTraverseRoot(Node& rootNode, bool& matchTraverseRoot
) const |
384 { | 382 { |
385 // We need to return the matches in document order. To use id lookup while t
here is possiblity of multiple matches | 383 // We need to return the matches in document order. To use id lookup while t
here is possiblity of multiple matches |
386 // we would need to sort the results. For now, just traverse the document in
that case. | 384 // we would need to sort the results. For now, just traverse the document in
that case. |
387 ASSERT(rootNode); | |
388 ASSERT(m_selectors.size() == 1); | 385 ASSERT(m_selectors.size() == 1); |
389 ASSERT(m_selectors[0].selector); | 386 ASSERT(m_selectors[0].selector); |
390 | 387 |
391 bool matchSingleNode = true; | 388 bool matchSingleNode = true; |
392 bool startFromParent = false; | 389 bool startFromParent = false; |
393 for (const CSSSelector* selector = m_selectors[0].selector; selector; select
or = selector->tagHistory()) { | 390 for (const CSSSelector* selector = m_selectors[0].selector; selector; select
or = selector->tagHistory()) { |
394 if (selector->m_match == CSSSelector::Id && !rootNode->document().contai
nsMultipleElementsWithId(selector->value())) { | 391 if (selector->m_match == CSSSelector::Id && !rootNode.document().contain
sMultipleElementsWithId(selector->value())) { |
395 Element* element = rootNode->treeScope().getElementById(selector->va
lue()); | 392 Element* element = rootNode.treeScope().getElementById(selector->val
ue()); |
396 if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf
(rootNode))) | 393 Node* adjustedRootNode = &rootNode; |
397 rootNode = element; | 394 if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf
(&rootNode))) |
| 395 adjustedRootNode = element; |
398 else if (!element || matchSingleNode) | 396 else if (!element || matchSingleNode) |
399 rootNode = 0; | 397 adjustedRootNode = 0; |
400 if (matchSingleNode) { | 398 if (matchSingleNode) { |
401 matchTraverseRoot = true; | 399 matchTraverseRoot = true; |
402 return rootNode; | 400 return adjustedRootNode; |
403 } | 401 } |
404 if (startFromParent && rootNode) | 402 if (startFromParent && adjustedRootNode) |
405 rootNode = rootNode->parentNode(); | 403 adjustedRootNode = adjustedRootNode->parentNode(); |
406 matchTraverseRoot = false; | 404 matchTraverseRoot = false; |
407 return rootNode; | 405 return adjustedRootNode; |
408 } | 406 } |
409 if (selector->relation() == CSSSelector::SubSelector) | 407 if (selector->relation() == CSSSelector::SubSelector) |
410 continue; | 408 continue; |
411 matchSingleNode = false; | 409 matchSingleNode = false; |
412 if (selector->relation() == CSSSelector::DirectAdjacent || selector->rel
ation() == CSSSelector::IndirectAdjacent) | 410 if (selector->relation() == CSSSelector::DirectAdjacent || selector->rel
ation() == CSSSelector::IndirectAdjacent) |
413 startFromParent = true; | 411 startFromParent = true; |
414 else | 412 else |
415 startFromParent = false; | 413 startFromParent = false; |
416 } | 414 } |
417 matchTraverseRoot = false; | 415 matchTraverseRoot = false; |
418 return rootNode; | 416 return &rootNode; |
419 } | 417 } |
420 | 418 |
421 Element* SelectorDataList::executeSlowQueryFirst(Node* rootNode) const | 419 Element* SelectorDataList::executeSlowQueryFirst(Node& rootNode) const |
422 { | 420 { |
423 for (Element* element = ElementTraversal::firstWithin(rootNode); element; el
ement = ElementTraversal::next(element, rootNode)) { | 421 for (Element* element = ElementTraversal::firstWithin(&rootNode); element; e
lement = ElementTraversal::next(element, &rootNode)) { |
424 for (unsigned i = 0; i < m_selectors.size(); ++i) { | 422 for (unsigned i = 0; i < m_selectors.size(); ++i) { |
425 if (selectorMatches(m_selectors[i], element, rootNode)) | 423 if (selectorMatches(m_selectors[i], *element, rootNode)) |
426 return element; | 424 return element; |
427 } | 425 } |
428 } | 426 } |
429 return 0; | 427 return 0; |
430 } | 428 } |
431 | 429 |
432 Element* SelectorDataList::executeQueryFirst(Node* rootNode) const | 430 Element* SelectorDataList::executeQueryFirst(Node& rootNode) const |
433 { | 431 { |
434 if (!canUseFastQuery(rootNode)) | 432 if (!canUseFastQuery(rootNode)) |
435 return executeSlowQueryFirst(rootNode); | 433 return executeSlowQueryFirst(rootNode); |
436 | 434 |
437 | 435 |
438 const CSSSelector* selector = m_selectors[0].selector; | 436 const CSSSelector* selector = m_selectors[0].selector; |
439 ASSERT(selector); | 437 ASSERT(selector); |
440 | 438 |
441 if (!selector->tagHistory()) { | 439 if (!selector->tagHistory()) { |
442 // Fast path for querySelector('#id'), querySelector('.foo'), and queryS
elector('div'). | 440 // Fast path for querySelector('#id'), querySelector('.foo'), and queryS
elector('div'). |
443 // Many web developers uses querySelector with these simple selectors. | 441 // Many web developers uses querySelector with these simple selectors. |
444 switch (selector->m_match) { | 442 switch (selector->m_match) { |
445 case CSSSelector::Id: | 443 case CSSSelector::Id: |
446 { | 444 { |
447 if (rootNode->document().containsMultipleElementsWithId(selector
->value())) | 445 if (rootNode.document().containsMultipleElementsWithId(selector-
>value())) |
448 break; | 446 break; |
449 Element* element = rootNode->treeScope().getElementById(selector
->value()); | 447 Element* element = rootNode.treeScope().getElementById(selector-
>value()); |
450 return element && (isTreeScopeRoot(rootNode) || element->isDesce
ndantOf(rootNode)) ? element : 0; | 448 return element && (isTreeScopeRoot(rootNode) || element->isDesce
ndantOf(&rootNode)) ? element : 0; |
451 } | 449 } |
452 case CSSSelector::Class: | 450 case CSSSelector::Class: |
453 return findElementByClassName(rootNode, selector->value()); | 451 return findElementByClassName(rootNode, selector->value()); |
454 case CSSSelector::Tag: | 452 case CSSSelector::Tag: |
455 return findElementByTagName(rootNode, selector->tagQName()); | 453 return findElementByTagName(rootNode, selector->tagQName()); |
456 default: | 454 default: |
457 break; // If we need another fast path, add here. | 455 break; // If we need another fast path, add here. |
458 } | 456 } |
459 } | 457 } |
460 | 458 |
461 bool matchTraverseRoot; | 459 bool matchTraverseRoot; |
462 Node* traverseRootNode = findTraverseRoot(rootNode, matchTraverseRoot); | 460 Node* traverseRootNode = findTraverseRoot(rootNode, matchTraverseRoot); |
463 if (!traverseRootNode) | 461 if (!traverseRootNode) |
464 return 0; | 462 return 0; |
465 if (matchTraverseRoot) { | 463 if (matchTraverseRoot) { |
466 ASSERT(m_selectors.size() == 1); | 464 ASSERT(m_selectors.size() == 1); |
467 ASSERT(traverseRootNode->isElementNode()); | 465 ASSERT(traverseRootNode->isElementNode()); |
468 Element* element = toElement(traverseRootNode); | 466 Element& element = toElement(*traverseRootNode); |
469 return selectorMatches(m_selectors[0], element, rootNode) ? element : 0; | 467 return selectorMatches(m_selectors[0], element, rootNode) ? &element : 0
; |
470 } | 468 } |
471 | 469 |
472 for (Element* element = ElementTraversal::firstWithin(traverseRootNode); ele
ment; element = ElementTraversal::next(element, traverseRootNode)) { | 470 for (Element* element = ElementTraversal::firstWithin(traverseRootNode); ele
ment; element = ElementTraversal::next(element, traverseRootNode)) { |
473 if (selectorMatches(m_selectors[0], element, rootNode)) | 471 if (selectorMatches(m_selectors[0], *element, rootNode)) |
474 return element; | 472 return element; |
475 } | 473 } |
476 return 0; | 474 return 0; |
477 } | 475 } |
478 | 476 |
479 SelectorQuery::SelectorQuery(const CSSSelectorList& selectorList) | 477 SelectorQuery::SelectorQuery(const CSSSelectorList& selectorList) |
480 : m_selectorList(selectorList) | 478 : m_selectorList(selectorList) |
481 { | 479 { |
482 m_selectors.initialize(m_selectorList); | 480 m_selectors.initialize(m_selectorList); |
483 } | 481 } |
484 | 482 |
485 bool SelectorQuery::matches(Element* element) const | 483 bool SelectorQuery::matches(Element& element) const |
486 { | 484 { |
487 return m_selectors.matches(element); | 485 return m_selectors.matches(element); |
488 } | 486 } |
489 | 487 |
490 PassRefPtr<NodeList> SelectorQuery::queryAll(Node* rootNode) const | 488 PassRefPtr<NodeList> SelectorQuery::queryAll(Node& rootNode) const |
491 { | 489 { |
492 return m_selectors.queryAll(rootNode); | 490 return m_selectors.queryAll(rootNode); |
493 } | 491 } |
494 | 492 |
495 PassRefPtr<Element> SelectorQuery::queryFirst(Node* rootNode) const | 493 PassRefPtr<Element> SelectorQuery::queryFirst(Node& rootNode) const |
496 { | 494 { |
497 return m_selectors.queryFirst(rootNode); | 495 return m_selectors.queryFirst(rootNode); |
498 } | 496 } |
499 | 497 |
500 SelectorQuery* SelectorQueryCache::add(const AtomicString& selectors, const Docu
ment& document, ExceptionState& es) | 498 SelectorQuery* SelectorQueryCache::add(const AtomicString& selectors, const Docu
ment& document, ExceptionState& es) |
501 { | 499 { |
502 HashMap<AtomicString, OwnPtr<SelectorQuery> >::iterator it = m_entries.find(
selectors); | 500 HashMap<AtomicString, OwnPtr<SelectorQuery> >::iterator it = m_entries.find(
selectors); |
503 if (it != m_entries.end()) | 501 if (it != m_entries.end()) |
504 return it->value.get(); | 502 return it->value.get(); |
505 | 503 |
(...skipping 21 matching lines...) Expand all Loading... |
527 m_entries.add(selectors, selectorQuery.release()); | 525 m_entries.add(selectors, selectorQuery.release()); |
528 return rawSelectorQuery; | 526 return rawSelectorQuery; |
529 } | 527 } |
530 | 528 |
531 void SelectorQueryCache::invalidate() | 529 void SelectorQueryCache::invalidate() |
532 { | 530 { |
533 m_entries.clear(); | 531 m_entries.clear(); |
534 } | 532 } |
535 | 533 |
536 } | 534 } |
OLD | NEW |