Bug 511147: Avoid the slow greedy-operator path for A > B ~ C selectors. r=dbaron

This commit is contained in:
Zack Weinberg 2009-08-20 14:52:47 -07:00
Родитель 4e96b6eb1b
Коммит 59e4f8561c
2 изменённых файлов: 40 добавлений и 5 удалений

Просмотреть файл

@ -1903,11 +1903,12 @@ static PRBool SelectorMatchesTree(RuleProcessorData& aPrevData,
// combinator is different, but we can make an exception for
// sibling, then parent, since a sibling's parent is always the
// same.
if ((NS_IS_GREEDY_OPERATOR(selector->mOperator)) &&
(selector->mNext) &&
(selector->mNext->mOperator != selector->mOperator) &&
if (NS_IS_GREEDY_OPERATOR(selector->mOperator) &&
selector->mNext &&
selector->mNext->mOperator != selector->mOperator &&
!(selector->mOperator == '~' &&
selector->mNext->mOperator == PRUnichar(0))) {
(selector->mNext->mOperator == PRUnichar(0) ||
selector->mNext->mOperator == PRUnichar('>')))) {
// pretend the selector didn't match, and step through content
// while testing the same selector

Просмотреть файл

@ -490,6 +490,20 @@ function run() {
return result;
}
}
function classset(classes) { // takes an array of classes
return function classset_filter(doc) {
var i, j, els;
var result = [];
for (i = 0; i < classes.length; i++) {
els = doc.getElementsByClassName(classes[i]);
for (j = 0; j < els.length; j++) {
result.push(els[j]);
}
}
return result;
}
}
function emptyset(doc) { return []; }
test_parseable(":first-child");
test_parseable(":last-child");
test_parseable(":only-child");
@ -579,6 +593,27 @@ function run() {
test_selector_in_html("#a > #c div", four_children,
idset([]), idset(["a", "b", "c", "d"]));
// More descendant combinator greediness (bug 511147)
test_selector_in_html(".a > .b ~ .match", '<div class="a"><div class="b"></div><div class="match"></div></div>',
classset(["match"]), classset(["a", "b"]));
test_selector_in_html(".a > .b ~ .match", '<div class="a"><div class="b"></div><div class="x"></div><div class="match"></div></div>',
classset(["match"]), classset(["a", "b", "x"]));
test_selector_in_html(".a > .b ~ .match", '<div class="a"><div class="b"><p>filler filler <i>filler</i> filler</p></div><div class="match"></div></div>',
classset(["match"]), classset(["a", "b", "x"]));
test_selector_in_html(".a > .b ~ .match", '<div class="a"><div class="x"><p>filler filler <i>filler</i> filler</p></div><div></div><div class="b"></div><div></div><div class="x"><p>filler filler <i>filler</i> filler</p></div><div class="match"></div></div>',
classset(["match"]), classset(["a", "b", "x"]));
test_selector_in_html(".a > .b ~ .match", '<div class="a"><div class="b"></div><div class="match"></div><div class="match"></div></div>',
classset(["match"]), classset(["a", "b"]));
test_selector_in_html(".a > .b ~ .nomatch", '<div class="a"><div><div class="b"></div><div class="nomatch"></div></div></div>',
emptyset, classset(["a", "b", "nomatch"]));
test_selector_in_html(".a > .b ~ .nomatch", '<div class="a"><div><div class="b"></div><div class="nomatch"></div></div><div class="nomatch"></div></div>',
emptyset, classset(["a", "b", "nomatch"]));
test_selector_in_html(".a > .b ~ .nomatch", '<div class="a"><div class="b"></div><div><div class="nomatch"></div></div><div></div></div>',
emptyset, classset(["a", "b", "nomatch"]));
test_selector_in_html(".a > .b ~ .nomatch", '<div class="a"><div class="b"></div></div><div class="nomatch"></div>',
emptyset, classset(["a", "b", "nomatch"]));
// Test serialization of pseudo-elements.
should_serialize_to("p:first-letter", "p:first-letter");
should_serialize_to("div>p:first-letter", "div > p:first-letter");
@ -678,4 +713,3 @@ function deferred_tests_onload(event)
</pre>
</body>
</html>