in lib/src/query_selector.dart [64:124]
bool visitSelector(Selector node) {
final old = _element;
var result = true;
// Note: evaluate selectors right-to-left as it's more efficient.
int? combinator;
for (var s in node.simpleSelectorSequences.reversed) {
if (combinator == null) {
result = s.simpleSelector.visit(this) as bool;
} else if (combinator == TokenKind.COMBINATOR_DESCENDANT) {
// descendant combinator
// http://dev.w3.org/csswg/selectors-4/#descendant-combinators
do {
_element = _element!.parent;
} while (_element != null && !(s.simpleSelector.visit(this) as bool));
if (_element == null) result = false;
} else if (combinator == TokenKind.COMBINATOR_TILDE) {
// Following-sibling combinator
// http://dev.w3.org/csswg/selectors-4/#general-sibling-combinators
do {
_element = _element!.previousElementSibling;
} while (_element != null && !(s.simpleSelector.visit(this) as bool));
if (_element == null) result = false;
}
if (!result) break;
switch (s.combinator) {
case TokenKind.COMBINATOR_PLUS:
// Next-sibling combinator
// http://dev.w3.org/csswg/selectors-4/#adjacent-sibling-combinators
_element = _element!.previousElementSibling;
break;
case TokenKind.COMBINATOR_GREATER:
// Child combinator
// http://dev.w3.org/csswg/selectors-4/#child-combinators
_element = _element!.parent;
break;
case TokenKind.COMBINATOR_DESCENDANT:
case TokenKind.COMBINATOR_TILDE:
// We need to iterate through all siblings or parents.
// For now, just remember what the combinator was.
combinator = s.combinator;
break;
case TokenKind.COMBINATOR_NONE:
break;
default:
throw _unsupported(node);
}
if (_element == null) {
result = false;
break;
}
}
_element = old;
return result;
}