mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 449447. Reuse the caching GetNthIndex for first/last/onlyChild selectors
This commit is contained in:
parent
86fc9bf82f
commit
fbb19aff3d
@ -1005,24 +1005,26 @@ RuleProcessorData::GetNthIndex(PRBool aIsOfType, PRBool aIsFromEnd,
|
||||
PRInt32 result = 1;
|
||||
nsIContent* parent = mParentContent;
|
||||
|
||||
PRUint32 cur;
|
||||
PRUint32 childCount = parent->GetChildCount();
|
||||
nsIContent * const * curChildPtr = parent->GetChildArray();
|
||||
PRInt32 increment;
|
||||
nsIContent * const * stopPtr;
|
||||
if (aIsFromEnd) {
|
||||
cur = parent->GetChildCount() - 1;
|
||||
stopPtr = curChildPtr - 1;
|
||||
curChildPtr += childCount - 1;
|
||||
increment = -1;
|
||||
} else {
|
||||
cur = 0;
|
||||
increment = 1;
|
||||
stopPtr = curChildPtr + childCount;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
nsIContent* child = parent->GetChildAt(cur);
|
||||
if (!child) {
|
||||
for ( ; ; curChildPtr += increment) {
|
||||
if (curChildPtr == stopPtr) {
|
||||
// mContent is the root of an anonymous content subtree.
|
||||
result = 0; // special value to indicate that it is not at any index
|
||||
break;
|
||||
}
|
||||
cur += increment;
|
||||
nsIContent* child = *curChildPtr;
|
||||
if (child == mContent)
|
||||
break;
|
||||
if (child->IsNodeOfType(nsINode::eELEMENT) &&
|
||||
@ -1190,68 +1192,57 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
||||
for (nsPseudoClassList* pseudoClass = aSelector->mPseudoClassList;
|
||||
pseudoClass && result; pseudoClass = pseudoClass->mNext) {
|
||||
PRInt32 stateToCheck = 0;
|
||||
if ((nsCSSPseudoClasses::firstChild == pseudoClass->mAtom) ||
|
||||
(nsCSSPseudoClasses::firstNode == pseudoClass->mAtom) ) {
|
||||
nsIContent *firstChild = nsnull;
|
||||
if (nsCSSPseudoClasses::firstNode == pseudoClass->mAtom) {
|
||||
nsIContent *firstNode = nsnull;
|
||||
nsIContent *parent = data.mParentContent;
|
||||
if (parent) {
|
||||
if (setNodeFlags)
|
||||
parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
|
||||
|
||||
PRBool acceptNonWhitespace =
|
||||
nsCSSPseudoClasses::firstNode == pseudoClass->mAtom;
|
||||
PRInt32 index = -1;
|
||||
do {
|
||||
firstChild = parent->GetChildAt(++index);
|
||||
// stop at first non-comment and non-whitespace node (and
|
||||
// non-text node for firstChild)
|
||||
} while (firstChild &&
|
||||
!IsSignificantChild(firstChild, acceptNonWhitespace, PR_FALSE));
|
||||
firstNode = parent->GetChildAt(++index);
|
||||
// stop at first non-comment and non-whitespace node
|
||||
} while (firstNode &&
|
||||
!IsSignificantChild(firstNode, PR_TRUE, PR_FALSE));
|
||||
}
|
||||
result = (data.mContent == firstChild);
|
||||
result = (data.mContent == firstNode);
|
||||
}
|
||||
else if ((nsCSSPseudoClasses::lastChild == pseudoClass->mAtom) ||
|
||||
(nsCSSPseudoClasses::lastNode == pseudoClass->mAtom)) {
|
||||
nsIContent *lastChild = nsnull;
|
||||
else if (nsCSSPseudoClasses::lastNode == pseudoClass->mAtom) {
|
||||
nsIContent *lastNode = nsnull;
|
||||
nsIContent *parent = data.mParentContent;
|
||||
if (parent) {
|
||||
if (setNodeFlags)
|
||||
parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
|
||||
|
||||
PRBool acceptNonWhitespace =
|
||||
nsCSSPseudoClasses::lastNode == pseudoClass->mAtom;
|
||||
PRUint32 index = parent->GetChildCount();
|
||||
do {
|
||||
lastChild = parent->GetChildAt(--index);
|
||||
// stop at first non-comment and non-whitespace node (and
|
||||
// non-text node for lastChild)
|
||||
} while (lastChild &&
|
||||
!IsSignificantChild(lastChild, acceptNonWhitespace, PR_FALSE));
|
||||
lastNode = parent->GetChildAt(--index);
|
||||
// stop at first non-comment and non-whitespace node
|
||||
} while (lastNode &&
|
||||
!IsSignificantChild(lastNode, PR_TRUE, PR_FALSE));
|
||||
}
|
||||
result = (data.mContent == lastChild);
|
||||
result = (data.mContent == lastNode);
|
||||
}
|
||||
else if (nsCSSPseudoClasses::onlyChild == pseudoClass->mAtom) {
|
||||
nsIContent *onlyChild = nsnull;
|
||||
nsIContent *moreChild = nsnull;
|
||||
else if (nsCSSPseudoClasses::firstChild == pseudoClass->mAtom ||
|
||||
nsCSSPseudoClasses::lastChild == pseudoClass->mAtom ||
|
||||
nsCSSPseudoClasses::onlyChild == pseudoClass->mAtom) {
|
||||
nsIContent *parent = data.mParentContent;
|
||||
if (parent) {
|
||||
const PRBool checkFirst =
|
||||
pseudoClass->mAtom != nsCSSPseudoClasses::lastChild;
|
||||
const PRBool checkLast =
|
||||
pseudoClass->mAtom != nsCSSPseudoClasses::firstChild;
|
||||
if (setNodeFlags)
|
||||
parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
|
||||
|
||||
PRInt32 index = -1;
|
||||
do {
|
||||
onlyChild = parent->GetChildAt(++index);
|
||||
// stop at first non-comment, non-whitespace and non-text node
|
||||
} while (onlyChild &&
|
||||
!IsSignificantChild(onlyChild, PR_FALSE, PR_FALSE));
|
||||
if (data.mContent == onlyChild) {
|
||||
// see if there's any more
|
||||
do {
|
||||
moreChild = parent->GetChildAt(++index);
|
||||
} while (moreChild && !IsSignificantChild(moreChild, PR_FALSE, PR_FALSE));
|
||||
}
|
||||
result = (!checkFirst ||
|
||||
data.GetNthIndex(PR_FALSE, PR_FALSE, PR_TRUE) == 1) &&
|
||||
(!checkLast ||
|
||||
data.GetNthIndex(PR_FALSE, PR_TRUE, PR_TRUE) == 1);
|
||||
} else {
|
||||
result = PR_FALSE;
|
||||
}
|
||||
result = (data.mContent == onlyChild && moreChild == nsnull);
|
||||
}
|
||||
else if (nsCSSPseudoClasses::nthChild == pseudoClass->mAtom ||
|
||||
nsCSSPseudoClasses::nthLastChild == pseudoClass->mAtom ||
|
||||
|
@ -377,6 +377,61 @@ function run() {
|
||||
test_selector_in_html(":nth-last-of-type(6)", seven_ps,
|
||||
pset([2]), pset([1, 3, 4, 5, 6, 7]));
|
||||
|
||||
// Test [first|last|only]-[child|node|of-type]
|
||||
var interesting_doc = "<!----> <div id='p1'> <!---->x<p id='s1'></p> <!----><p id='s2'></p> <!----></div> <!----><p id='p2'> <!----><span id='s3'></span> <!----><span id='s4'></span> <!---->x</p> <!----><div id='p3'> <!----><p id='s5'></p> <!----></div> <!---->";
|
||||
function idset(ids) { // takes an array of ids
|
||||
return function idset_filter(doc) {
|
||||
var result = [];
|
||||
for each (var id in ids)
|
||||
result.push(doc.getElementById(id));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
test_parseable(":first-child");
|
||||
test_parseable(":last-child");
|
||||
test_parseable(":only-child");
|
||||
test_parseable(":-moz-first-node");
|
||||
test_parseable(":-moz-last-node");
|
||||
test_parseable(":first-of-type");
|
||||
test_parseable(":last-of-type");
|
||||
test_parseable(":only-of-type");
|
||||
test_selector_in_html(":first-child", seven_ps,
|
||||
pset([1]), pset([2, 3, 4, 5, 6, 7]));
|
||||
test_selector_in_html(":first-child", interesting_doc,
|
||||
idset(["p1", "s1", "s3", "s5"]),
|
||||
idset(["s2", "p2", "s4", "p3"]));
|
||||
test_selector_in_html(":-moz-first-node", interesting_doc,
|
||||
idset(["p1", "s3", "s5"]),
|
||||
idset(["s1", "s2", "p2", "s4", "p3"]));
|
||||
test_selector_in_html(":last-child", seven_ps,
|
||||
pset([7]), pset([1, 2, 3, 4, 5, 6]));
|
||||
test_selector_in_html(":last-child", interesting_doc,
|
||||
idset(["s2", "s4", "p3", "s5"]),
|
||||
idset(["p1", "s1", "p2", "s3"]));
|
||||
test_selector_in_html(":-moz-last-node", interesting_doc,
|
||||
idset(["s2", "p3", "s5"]),
|
||||
idset(["p1", "s1", "p2", "s3", "s4"]));
|
||||
test_selector_in_html(":only-child", seven_ps,
|
||||
pset([]), pset([1, 2, 3, 4, 5, 6, 7]));
|
||||
test_selector_in_html(":only-child", interesting_doc,
|
||||
idset(["s5"]),
|
||||
idset(["p1", "s1", "s2", "p2", "s3", "s4", "p3"]));
|
||||
test_selector_in_html(":first-of-type", seven_ps,
|
||||
pset([1]), pset([2, 3, 4, 5, 6, 7]));
|
||||
test_selector_in_html(":first-of-type", interesting_doc,
|
||||
idset(["p1", "s1", "p2", "s3", "s5"]),
|
||||
idset(["s2", "s4", "p3"]));
|
||||
test_selector_in_html(":last-of-type", seven_ps,
|
||||
pset([7]), pset([1, 2, 3, 4, 5, 6]));
|
||||
test_selector_in_html(":last-of-type", interesting_doc,
|
||||
idset(["s2", "p2", "s4", "p3", "s5"]),
|
||||
idset(["p1", "s1", "s3"]));
|
||||
test_selector_in_html(":only-of-type", seven_ps,
|
||||
pset([]), pset([1, 2, 3, 4, 5, 6, 7]));
|
||||
test_selector_in_html(":only-of-type", interesting_doc,
|
||||
idset(["p2", "s5"]),
|
||||
idset(["p1", "s1", "s2", "s3", "s4", "p3"]));
|
||||
|
||||
// And a bunch of tests for the of-type aspect of :nth-of-type() and
|
||||
// :nth-last-of-type(). Note that the last div here contains two
|
||||
// children.
|
||||
|
Loading…
Reference in New Issue
Block a user