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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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::Query
ingRules); |
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->isC
ontainerNode() ? 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); | 161 ASSERT(targetElement); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 { | 216 { |
217 for (Element* element = ElementTraversal::firstWithin(rootNode); element; el
ement = ElementTraversal::next(element, rootNode)) { | 217 for (Element* element = ElementTraversal::firstWithin(rootNode); element; el
ement = ElementTraversal::next(element, rootNode)) { |
218 if (SelectorChecker::tagMatches(element, tagName)) | 218 if (SelectorChecker::tagMatches(element, tagName)) |
219 return element; | 219 return element; |
220 } | 220 } |
221 return 0; | 221 return 0; |
222 } | 222 } |
223 | 223 |
224 inline bool SelectorDataList::canUseFastQuery(Node* rootNode) const | 224 inline bool SelectorDataList::canUseFastQuery(Node* rootNode) const |
225 { | 225 { |
226 return m_selectors.size() == 1 && rootNode->inDocument() && !rootNode->docum
ent()->inQuirksMode(); | 226 return m_selectors.size() == 1 && rootNode->inDocument() && !rootNode->docum
ent().inQuirksMode(); |
227 } | 227 } |
228 | 228 |
229 // If returns true, traversalRoots has the elements that may match the selector
query. | 229 // If returns true, traversalRoots has the elements that may match the selector
query. |
230 // | 230 // |
231 // If returns false, traversalRoots has the rootNode parameter or descendants of
rootNode representing | 231 // If returns false, traversalRoots has the rootNode parameter or descendants of
rootNode representing |
232 // the subtree for which we can limit the querySelector traversal. | 232 // the subtree for which we can limit the querySelector traversal. |
233 // | 233 // |
234 // The travseralRoots may be empty, regardless of the returned bool value, if th
is method finds that the selectors won't | 234 // The travseralRoots may be empty, regardless of the returned bool value, if th
is method finds that the selectors won't |
235 // match any element. | 235 // match any element. |
236 PassOwnPtr<SimpleNodeList> SelectorDataList::findTraverseRoots(Node* rootNode, b
ool& matchTraverseRoots) const | 236 PassOwnPtr<SimpleNodeList> SelectorDataList::findTraverseRoots(Node* rootNode, b
ool& matchTraverseRoots) const |
237 { | 237 { |
238 // We need to return the matches in document order. To use id lookup while t
here is possiblity of multiple matches | 238 // We need to return the matches in document order. To use id lookup while t
here is possiblity of multiple matches |
239 // we would need to sort the results. For now, just traverse the document in
that case. | 239 // we would need to sort the results. For now, just traverse the document in
that case. |
240 ASSERT(rootNode); | 240 ASSERT(rootNode); |
241 ASSERT(m_selectors.size() == 1); | 241 ASSERT(m_selectors.size() == 1); |
242 ASSERT(m_selectors[0].selector); | 242 ASSERT(m_selectors[0].selector); |
243 | 243 |
244 bool isRightmostSelector = true; | 244 bool isRightmostSelector = true; |
245 bool startFromParent = false; | 245 bool startFromParent = false; |
246 | 246 |
247 for (const CSSSelector* selector = m_selectors[0].selector; selector; select
or = selector->tagHistory()) { | 247 for (const CSSSelector* selector = m_selectors[0].selector; selector; select
or = selector->tagHistory()) { |
248 if (selector->m_match == CSSSelector::Id && !rootNode->document()->conta
insMultipleElementsWithId(selector->value())) { | 248 if (selector->m_match == CSSSelector::Id && !rootNode->document().contai
nsMultipleElementsWithId(selector->value())) { |
249 Element* element = rootNode->treeScope()->getElementById(selector->v
alue()); | 249 Element* element = rootNode->treeScope()->getElementById(selector->v
alue()); |
250 if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf
(rootNode))) | 250 if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf
(rootNode))) |
251 rootNode = element; | 251 rootNode = element; |
252 else if (!element || isRightmostSelector) | 252 else if (!element || isRightmostSelector) |
253 rootNode = 0; | 253 rootNode = 0; |
254 if (isRightmostSelector) { | 254 if (isRightmostSelector) { |
255 matchTraverseRoots = true; | 255 matchTraverseRoots = true; |
256 return adoptPtr(new SingleNodeList(rootNode)); | 256 return adoptPtr(new SingleNodeList(rootNode)); |
257 } | 257 } |
258 if (startFromParent && rootNode) | 258 if (startFromParent && rootNode) |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 ASSERT(m_selectors.size() == 1); | 306 ASSERT(m_selectors.size() == 1); |
307 ASSERT(m_selectors[0].selector); | 307 ASSERT(m_selectors[0].selector); |
308 | 308 |
309 const CSSSelector* firstSelector = m_selectors[0].selector; | 309 const CSSSelector* firstSelector = m_selectors[0].selector; |
310 | 310 |
311 if (!firstSelector->tagHistory()) { | 311 if (!firstSelector->tagHistory()) { |
312 // Fast path for querySelectorAll('#id'), querySelectorAl('.foo'), and q
uerySelectorAll('div'). | 312 // Fast path for querySelectorAll('#id'), querySelectorAl('.foo'), and q
uerySelectorAll('div'). |
313 switch (firstSelector->m_match) { | 313 switch (firstSelector->m_match) { |
314 case CSSSelector::Id: | 314 case CSSSelector::Id: |
315 { | 315 { |
316 if (rootNode->document()->containsMultipleElementsWithId(firstSe
lector->value())) | 316 if (rootNode->document().containsMultipleElementsWithId(firstSel
ector->value())) |
317 break; | 317 break; |
318 | 318 |
319 // Just the same as getElementById. | 319 // Just the same as getElementById. |
320 Element* element = rootNode->treeScope()->getElementById(firstSe
lector->value()); | 320 Element* element = rootNode->treeScope()->getElementById(firstSe
lector->value()); |
321 if (element && (isTreeScopeRoot(rootNode) || element->isDescenda
ntOf(rootNode))) | 321 if (element && (isTreeScopeRoot(rootNode) || element->isDescenda
ntOf(rootNode))) |
322 matchedElements.append(element); | 322 matchedElements.append(element); |
323 return; | 323 return; |
324 } | 324 } |
325 case CSSSelector::Class: | 325 case CSSSelector::Class: |
326 return collectElementsByClassName(rootNode, firstSelector->value(),
matchedElements); | 326 return collectElementsByClassName(rootNode, firstSelector->value(),
matchedElements); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 { | 367 { |
368 // We need to return the matches in document order. To use id lookup while t
here is possiblity of multiple matches | 368 // We need to return the matches in document order. To use id lookup while t
here is possiblity of multiple matches |
369 // we would need to sort the results. For now, just traverse the document in
that case. | 369 // we would need to sort the results. For now, just traverse the document in
that case. |
370 ASSERT(rootNode); | 370 ASSERT(rootNode); |
371 ASSERT(m_selectors.size() == 1); | 371 ASSERT(m_selectors.size() == 1); |
372 ASSERT(m_selectors[0].selector); | 372 ASSERT(m_selectors[0].selector); |
373 | 373 |
374 bool matchSingleNode = true; | 374 bool matchSingleNode = true; |
375 bool startFromParent = false; | 375 bool startFromParent = false; |
376 for (const CSSSelector* selector = m_selectors[0].selector; selector; select
or = selector->tagHistory()) { | 376 for (const CSSSelector* selector = m_selectors[0].selector; selector; select
or = selector->tagHistory()) { |
377 if (selector->m_match == CSSSelector::Id && !rootNode->document()->conta
insMultipleElementsWithId(selector->value())) { | 377 if (selector->m_match == CSSSelector::Id && !rootNode->document().contai
nsMultipleElementsWithId(selector->value())) { |
378 Element* element = rootNode->treeScope()->getElementById(selector->v
alue()); | 378 Element* element = rootNode->treeScope()->getElementById(selector->v
alue()); |
379 if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf
(rootNode))) | 379 if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf
(rootNode))) |
380 rootNode = element; | 380 rootNode = element; |
381 else if (!element || matchSingleNode) | 381 else if (!element || matchSingleNode) |
382 rootNode = 0; | 382 rootNode = 0; |
383 if (matchSingleNode) { | 383 if (matchSingleNode) { |
384 matchTraverseRoot = true; | 384 matchTraverseRoot = true; |
385 return rootNode; | 385 return rootNode; |
386 } | 386 } |
387 if (startFromParent && rootNode) | 387 if (startFromParent && rootNode) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 | 420 |
421 const CSSSelector* selector = m_selectors[0].selector; | 421 const CSSSelector* selector = m_selectors[0].selector; |
422 ASSERT(selector); | 422 ASSERT(selector); |
423 | 423 |
424 if (!selector->tagHistory()) { | 424 if (!selector->tagHistory()) { |
425 // Fast path for querySelector('#id'), querySelector('.foo'), and queryS
elector('div'). | 425 // Fast path for querySelector('#id'), querySelector('.foo'), and queryS
elector('div'). |
426 // Many web developers uses querySelector with these simple selectors. | 426 // Many web developers uses querySelector with these simple selectors. |
427 switch (selector->m_match) { | 427 switch (selector->m_match) { |
428 case CSSSelector::Id: | 428 case CSSSelector::Id: |
429 { | 429 { |
430 if (rootNode->document()->containsMultipleElementsWithId(selecto
r->value())) | 430 if (rootNode->document().containsMultipleElementsWithId(selector
->value())) |
431 break; | 431 break; |
432 Element* element = rootNode->treeScope()->getElementById(selecto
r->value()); | 432 Element* element = rootNode->treeScope()->getElementById(selecto
r->value()); |
433 return element && (isTreeScopeRoot(rootNode) || element->isDesce
ndantOf(rootNode)) ? element : 0; | 433 return element && (isTreeScopeRoot(rootNode) || element->isDesce
ndantOf(rootNode)) ? element : 0; |
434 } | 434 } |
435 case CSSSelector::Class: | 435 case CSSSelector::Class: |
436 return findElementByClassName(rootNode, selector->value()); | 436 return findElementByClassName(rootNode, selector->value()); |
437 case CSSSelector::Tag: | 437 case CSSSelector::Tag: |
438 return findElementByTagName(rootNode, selector->tagQName()); | 438 return findElementByTagName(rootNode, selector->tagQName()); |
439 default: | 439 default: |
440 break; // If we need another fast path, add here. | 440 break; // If we need another fast path, add here. |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 m_entries.add(selectors, selectorQuery.release()); | 510 m_entries.add(selectors, selectorQuery.release()); |
511 return rawSelectorQuery; | 511 return rawSelectorQuery; |
512 } | 512 } |
513 | 513 |
514 void SelectorQueryCache::invalidate() | 514 void SelectorQueryCache::invalidate() |
515 { | 515 { |
516 m_entries.clear(); | 516 m_entries.clear(); |
517 } | 517 } |
518 | 518 |
519 } | 519 } |
OLD | NEW |