diff --git a/mozilla/content/html/style/src/nsCSSParser.cpp b/mozilla/content/html/style/src/nsCSSParser.cpp
index 0395e2b7e92..60d4a36fb01 100644
--- a/mozilla/content/html/style/src/nsCSSParser.cpp
+++ b/mozilla/content/html/style/src/nsCSSParser.cpp
@@ -1373,6 +1373,7 @@ static PRBool IsPseudoClass(const nsIAtom* aAtom)
(nsCSSAtoms::focusPseudo == aAtom) ||
(nsCSSAtoms::hoverPseudo == aAtom) ||
(nsCSSAtoms::langPseudo == aAtom) ||
+ (nsCSSAtoms::lastChildPseudo == aAtom) ||
(nsCSSAtoms::lastNodePseudo == aAtom) ||
(nsCSSAtoms::linkPseudo == aAtom) ||
(nsCSSAtoms::outOfDatePseudo == aAtom) ||
diff --git a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp
index 79492763fe6..88d1e66d931 100644
--- a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp
+++ b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp
@@ -2980,7 +2980,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
PRInt32 index = -1;
do {
parent->ChildAt(++index, firstChild);
- if (firstChild) { // skip text & comments (and whitespace for firstNode as well)
+ if (firstChild) { // stop at first non-comment and non-whitespace node (and non-text node for firstChild)
if (IsSignificantChild(firstChild, (nsCSSAtoms::firstNodePseudo == pseudoClass->mAtom))) {
break;
}
@@ -2994,7 +2994,8 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
result = PRBool(localTrue == (data.mContent == firstChild));
NS_IF_RELEASE(firstChild);
}
- else if (nsCSSAtoms::lastNodePseudo == pseudoClass->mAtom) {
+ else if ((nsCSSAtoms::lastChildPseudo == pseudoClass->mAtom) ||
+ (nsCSSAtoms::lastNodePseudo == pseudoClass->mAtom)) {
nsIContent* lastChild = nsnull;
nsIContent* parent = data.mParentContent;
if (parent) {
@@ -3002,8 +3003,8 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
parent->ChildCount(index);
do {
parent->ChildAt(--index, lastChild);
- if (lastChild) { // skip whitespace text & comments
- if (IsSignificantChild(lastChild, PR_TRUE)) {
+ if (lastChild) { // stop at first non-comment and non-whitespace node (and non-text node for lastChild)
+ if (IsSignificantChild(lastChild, (nsCSSAtoms::lastNodePseudo == pseudoClass->mAtom))) {
break;
}
NS_RELEASE(lastChild);
diff --git a/mozilla/content/shared/public/nsCSSAtomList.h b/mozilla/content/shared/public/nsCSSAtomList.h
index 9aa36e49a9e..c5aa8f806f3 100644
--- a/mozilla/content/shared/public/nsCSSAtomList.h
+++ b/mozilla/content/shared/public/nsCSSAtomList.h
@@ -56,6 +56,7 @@ CSS_ATOM(enabledPseudo, ":enabled")
CSS_ATOM(firstChildPseudo, ":first-child")
CSS_ATOM(firstNodePseudo, ":first-node")
+CSS_ATOM(lastChildPseudo, ":last-child")
CSS_ATOM(lastNodePseudo, ":last-node")
CSS_ATOM(focusPseudo, ":focus")
diff --git a/mozilla/layout/style/nsCSSParser.cpp b/mozilla/layout/style/nsCSSParser.cpp
index 0395e2b7e92..60d4a36fb01 100644
--- a/mozilla/layout/style/nsCSSParser.cpp
+++ b/mozilla/layout/style/nsCSSParser.cpp
@@ -1373,6 +1373,7 @@ static PRBool IsPseudoClass(const nsIAtom* aAtom)
(nsCSSAtoms::focusPseudo == aAtom) ||
(nsCSSAtoms::hoverPseudo == aAtom) ||
(nsCSSAtoms::langPseudo == aAtom) ||
+ (nsCSSAtoms::lastChildPseudo == aAtom) ||
(nsCSSAtoms::lastNodePseudo == aAtom) ||
(nsCSSAtoms::linkPseudo == aAtom) ||
(nsCSSAtoms::outOfDatePseudo == aAtom) ||
diff --git a/mozilla/layout/style/nsCSSStyleSheet.cpp b/mozilla/layout/style/nsCSSStyleSheet.cpp
index 79492763fe6..88d1e66d931 100644
--- a/mozilla/layout/style/nsCSSStyleSheet.cpp
+++ b/mozilla/layout/style/nsCSSStyleSheet.cpp
@@ -2980,7 +2980,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
PRInt32 index = -1;
do {
parent->ChildAt(++index, firstChild);
- if (firstChild) { // skip text & comments (and whitespace for firstNode as well)
+ if (firstChild) { // stop at first non-comment and non-whitespace node (and non-text node for firstChild)
if (IsSignificantChild(firstChild, (nsCSSAtoms::firstNodePseudo == pseudoClass->mAtom))) {
break;
}
@@ -2994,7 +2994,8 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
result = PRBool(localTrue == (data.mContent == firstChild));
NS_IF_RELEASE(firstChild);
}
- else if (nsCSSAtoms::lastNodePseudo == pseudoClass->mAtom) {
+ else if ((nsCSSAtoms::lastChildPseudo == pseudoClass->mAtom) ||
+ (nsCSSAtoms::lastNodePseudo == pseudoClass->mAtom)) {
nsIContent* lastChild = nsnull;
nsIContent* parent = data.mParentContent;
if (parent) {
@@ -3002,8 +3003,8 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
parent->ChildCount(index);
do {
parent->ChildAt(--index, lastChild);
- if (lastChild) { // skip whitespace text & comments
- if (IsSignificantChild(lastChild, PR_TRUE)) {
+ if (lastChild) { // stop at first non-comment and non-whitespace node (and non-text node for lastChild)
+ if (IsSignificantChild(lastChild, (nsCSSAtoms::lastNodePseudo == pseudoClass->mAtom))) {
break;
}
NS_RELEASE(lastChild);