Bug 606925 - Get rid of the "in foreign content" insertion mode. Check the namespace of the current node instead. rs=jonas, a=blocking2.0-betaN.
authorHenri Sivonen <hsivonen@iki.fi>
Thu, 09 Dec 2010 11:27:58 +0200
changeset 58959 a6ad532d8bf87882ebaabf723d566ba1a1ea5fc1
parent 58958 944cd0847692e5fbacabb1936e40780f7684dfe8
child 58960 0d032e29af92e5f7cfc9b81f654731cbad2219cd
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersjonas, blocking2
bugs606925
milestone2.0b8pre
Bug 606925 - Get rid of the "in foreign content" insertion mode. Check the namespace of the current node instead. rs=jonas, a=blocking2.0-betaN.
parser/html/javasrc/StateSnapshot.java
parser/html/javasrc/TreeBuilder.java
parser/html/nsAHtml5TreeBuilderState.h
parser/html/nsHtml5StateSnapshot.cpp
parser/html/nsHtml5StateSnapshot.h
parser/html/nsHtml5TreeBuilder.cpp
parser/html/nsHtml5TreeBuilder.h
parser/htmlparser/tests/mochitest/html5_tree_construction_exceptions.js
--- a/parser/html/javasrc/StateSnapshot.java
+++ b/parser/html/javasrc/StateSnapshot.java
@@ -38,43 +38,40 @@ public class StateSnapshot<T> implements
     private final T deepTreeSurrogateParent;
 
     private final int mode;
 
     private final int originalMode;
     
     private final boolean framesetOk;
 
-    private final boolean inForeign;
-
     private final boolean needToDropLF;
 
     private final boolean quirks;
 
     /**
      * @param stack
      * @param listOfActiveFormattingElements
      * @param formPointer
      * @param quirks 
      * @param needToDropLF 
      * @param foreignFlag 
      * @param originalMode 
      * @param mode 
      */
     StateSnapshot(StackNode<T>[] stack,
-            StackNode<T>[] listOfActiveFormattingElements, T formPointer, T headPointer, T deepTreeSurrogateParent, int mode, int originalMode, boolean framesetOk, boolean inForeign, boolean needToDropLF, boolean quirks) {
+            StackNode<T>[] listOfActiveFormattingElements, T formPointer, T headPointer, T deepTreeSurrogateParent, int mode, int originalMode, boolean framesetOk, boolean needToDropLF, boolean quirks) {
         this.stack = stack;
         this.listOfActiveFormattingElements = listOfActiveFormattingElements;
         this.formPointer = formPointer;
         this.headPointer = headPointer;
         this.deepTreeSurrogateParent = deepTreeSurrogateParent;
         this.mode = mode;
         this.originalMode = originalMode;
         this.framesetOk = framesetOk;
-        this.inForeign = inForeign;
         this.needToDropLF = needToDropLF;
         this.quirks = quirks;
     }
     
     /**
      * @see nu.validator.htmlparser.impl.TreeBuilderState#getStack()
      */
     public StackNode<T>[] getStack() {
@@ -136,25 +133,16 @@ public class StateSnapshot<T> implements
      * 
      * @return the framesetOk
      */
     public boolean isFramesetOk() {
         return framesetOk;
     }
 
     /**
-     * Returns the inForeign.
-     * 
-     * @return the inForeign
-     */
-    public boolean isInForeign() {
-        return inForeign;
-    }
-
-    /**
      * Returns the needToDropLF.
      * 
      * @return the needToDropLF
      */
     public boolean isNeedToDropLF() {
         return needToDropLF;
     }
 
--- a/parser/html/javasrc/TreeBuilder.java
+++ b/parser/html/javasrc/TreeBuilder.java
@@ -347,18 +347,16 @@ public abstract class TreeBuilder<T> imp
 
     private int originalMode = INITIAL;
     
     /**
      * Used only when moving back to IN_BODY.
      */
     private boolean framesetOk = true;
 
-    private boolean inForeign = false;
-
     protected Tokenizer tokenizer;
 
     // [NOCPP[
 
     protected ErrorHandler errorHandler;
 
     private DocumentModeHandler documentModeHandler;
 
@@ -547,24 +545,23 @@ public abstract class TreeBuilder<T> imp
                         contextName);
             } else {
                 tokenizer.setStateAndEndTagExpectation(Tokenizer.DATA, contextName);
             }
             contextName = null;
             contextNode = null;
         } else {
             mode = INITIAL;
-            inForeign = false;
         }
     }
 
     public final void doctype(@Local String name, String publicIdentifier,
             String systemIdentifier, boolean forceQuirks) throws SAXException {
         needToDropLF = false;
-        if (!inForeign) {
+        if (!isInForeign()) {
             switch (mode) {
                 case INITIAL:
                     // [NOCPP[
                     if (reportingDoctype) {
                         // ]NOCPP]
                         String emptyString = Portability.newEmptyString();
                         appendDoctypeToDocument(name == null ? "" : name,
                                 publicIdentifier == null ? emptyString
@@ -787,17 +784,17 @@ public abstract class TreeBuilder<T> imp
     public final void comment(@NoLength char[] buf, int start, int length)
             throws SAXException {
         needToDropLF = false;
         // [NOCPP[
         if (!wantingComments) {
             return;
         }
         // ]NOCPP]
-        if (!inForeign) {
+        if (!isInForeign()) {
             switch (mode) {
                 case INITIAL:
                 case BEFORE_HTML:
                 case AFTER_AFTER_BODY:
                 case AFTER_AFTER_FRAMESET:
                     /*
                      * A comment token Append a Comment node to the Document
                      * object with the data attribute set to the data given in
@@ -845,17 +842,17 @@ public abstract class TreeBuilder<T> imp
             needToDropLF = false;
         }
 
         // optimize the most common case
         switch (mode) {
             case IN_BODY:
             case IN_CELL:
             case IN_CAPTION:
-                if (!inForeign) {
+                if (!isInForeign()) {
                     reconstructTheActiveFormattingElements();
                 }
                 // fall through
             case TEXT:
                 accumulateCharacters(buf, start, length);
                 return;
             case IN_TABLE:
             case IN_TABLE_BODY:
@@ -904,17 +901,17 @@ public abstract class TreeBuilder<T> imp
                                                 - start);
                                         start = i;
                                     }
 
                                     /*
                                      * Reconstruct the active formatting
                                      * elements, if any.
                                      */
-                                    if (!inForeign) {
+                                    if (!isInForeign()) {
                                         flushCharacters();
                                         reconstructTheActiveFormattingElements();
                                     }
                                     /*
                                      * Append the token's character to the
                                      * current node.
                                      */
                                     break charactersloop;
@@ -1100,17 +1097,17 @@ public abstract class TreeBuilder<T> imp
                                         accumulateCharacters(buf, start, i
                                                 - start);
                                         start = i;
                                     }
                                     /*
                                      * Reconstruct the active formatting
                                      * elements, if any.
                                      */
-                                    if (!inForeign) {
+                                    if (!isInForeign()) {
                                         flushCharacters();
                                         reconstructTheActiveFormattingElements();
                                     }
                                     /*
                                      * Append the token's character to the
                                      * current node.
                                      */
                                     break charactersloop;
@@ -1214,25 +1211,25 @@ public abstract class TreeBuilder<T> imp
         }
     }
 
     /**
      * @see nu.validator.htmlparser.common.TokenHandler#zeroOriginatingReplacementCharacter()
      */
     public void zeroOriginatingReplacementCharacter()
             throws SAXException {
-        if (inForeign || mode == TEXT) {
+        if (isInForeign() || mode == TEXT) {
             characters(REPLACEMENT_CHARACTER, 0, 1);
         }
     }
 
     public final void eof() throws SAXException {
         flushCharacters();
         eofloop: for (;;) {
-            if (inForeign) {
+            if (isInForeign()) {
                 err("End of file in a foreign namespace context.");
                 break eofloop;
             }
             switch (mode) {
                 case INITIAL:
                     /*
                      * Parse error.
                      */
@@ -1428,29 +1425,23 @@ public abstract class TreeBuilder<T> imp
                     idLocations.put(id, new LocatorImpl(tokenizer));
                 }
             }
         }
         // ]NOCPP]
 
         int eltPos;
         needToDropLF = false;
-        boolean needsPostProcessing = false;
         starttagloop: for (;;) {
             int group = elementName.getGroup();
             @Local String name = elementName.name;
-            if (inForeign) {
+            if (isInForeign()) {
                 StackNode<T> currentNode = stack[currentPtr];
                 @NsUri String currNs = currentNode.ns;
-                if (("http://www.w3.org/1999/xhtml" == currNs)
-                        || currentNode.isHtmlIntegrationPoint()
-                        || (currNs == "http://www.w3.org/1998/Math/MathML" && ((currentNode.getGroup() == MI_MO_MN_MS_MTEXT && group != MGLYPH_OR_MALIGNMARK) || (currentNode.getGroup() == ANNOTATION_XML && group == SVG)))) {
-                    needsPostProcessing = true;
-                    // fall through to non-foreign behavior
-                } else {
+                if (!(currentNode.isHtmlIntegrationPoint() || (currNs == "http://www.w3.org/1998/Math/MathML" && ((currentNode.getGroup() == MI_MO_MN_MS_MTEXT && group != MGLYPH_OR_MALIGNMARK) || (currentNode.getGroup() == ANNOTATION_XML && group == SVG))))) {
                     switch (group) {
                         case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
                         case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
                         case BODY:
                         case BR:
                         case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR:
                         case DD_OR_DT:
                         case UL_OR_OL_OR_DL:
@@ -1465,33 +1456,27 @@ public abstract class TreeBuilder<T> imp
                         case PRE_OR_LISTING:
                         case TABLE:
                             err("HTML start tag \u201C"
                                     + name
                                     + "\u201D in a foreign namespace context.");
                             while (!isSpecialParentInForeign(stack[currentPtr])) {
                                 pop();
                             }
-                            if (!hasForeignInScope()) {
-                                inForeign = false;
-                            }
                             continue starttagloop;
                         case FONT:
                             if (attributes.contains(AttributeName.COLOR)
                                     || attributes.contains(AttributeName.FACE)
                                     || attributes.contains(AttributeName.SIZE)) {
                                 err("HTML start tag \u201C"
                                         + name
                                         + "\u201D in a foreign namespace context.");
                                 while (!isSpecialParentInForeign(stack[currentPtr])) {
                                     pop();
                                 }
-                                if (!hasForeignInScope()) {
-                                    inForeign = false;
-                                }
                                 continue starttagloop;
                             }
                             // else fall thru
                         default:
                             if ("http://www.w3.org/2000/svg" == currNs) {
                                 attributes.adjustForSvg();
                                 if (selfClosing) {
                                     appendVoidElementToCurrentMayFosterSVG(
@@ -2258,32 +2243,30 @@ public abstract class TreeBuilder<T> imp
                                 attributes.adjustForMath();
                                 if (selfClosing) {
                                     appendVoidElementToCurrentMayFosterMathML(
                                             elementName, attributes);
                                     selfClosing = false;
                                 } else {
                                     appendToCurrentNodeAndPushElementMayFosterMathML(
                                             elementName, attributes);
-                                    inForeign = true;
                                 }
                                 attributes = null; // CPP
                                 break starttagloop;
                             case SVG:
                                 reconstructTheActiveFormattingElements();
                                 attributes.adjustForSvg();
                                 if (selfClosing) {
                                     appendVoidElementToCurrentMayFosterSVG(
                                             elementName,
                                             attributes);
                                     selfClosing = false;
                                 } else {
                                     appendToCurrentNodeAndPushElementMayFosterSVG(
                                             elementName, attributes);
-                                    inForeign = true;
                                 }
                                 attributes = null; // CPP
                                 break starttagloop;
                             case CAPTION:
                             case COL:
                             case COLGROUP:
                             case TBODY_OR_THEAD_OR_TFOOT:
                             case TR:
@@ -2888,44 +2871,29 @@ public abstract class TreeBuilder<T> imp
                             break starttagloop;
                     }
                 case TEXT:
                     assert false;
                     break starttagloop; // Avoid infinite loop if the assertion
                                         // fails
             }
         }
-        if (needsPostProcessing && inForeign                && !hasForeignInScope()) {
-            /*
-             * If, after doing so, the insertion mode is still "in foreign
-             * content", but there is no element in scope that has a namespace
-             * other than the HTML namespace, switch the insertion mode to the
-             * secondary insertion mode.
-             */
-            inForeign = false;
-        }
         if (errorHandler != null && selfClosing) {
             errNoCheck("Self-closing syntax (\u201C/>\u201D) used on a non-void HTML element. Ignoring the slash and treating as a start tag.");
         }
         if (attributes != HtmlAttributes.EMPTY_ATTRIBUTES) {
             Portability.delete(attributes);
         }
     }
 
     private boolean isSpecialParentInForeign(StackNode<T> stackNode) {
         @NsUri String ns = stackNode.ns;
-        if ("http://www.w3.org/1999/xhtml" == ns) {
-            return true;
-        }
-        if (ns == "http://www.w3.org/2000/svg") {
-            return stackNode.getGroup() == FOREIGNOBJECT_OR_DESC
-                    || stackNode.getGroup() == TITLE;
-        }
-        assert ns == "http://www.w3.org/1998/Math/MathML" : "Unexpected namespace.";
-        return stackNode.getGroup() == MI_MO_MN_MS_MTEXT;
+        return ("http://www.w3.org/1999/xhtml" == ns)
+                || (stackNode.isHtmlIntegrationPoint())
+                || (("http://www.w3.org/1998/Math/MathML" == ns) && (stackNode.getGroup() == MI_MO_MN_MS_MTEXT));
     }
 
     /**
      * 
      * <p>
      * C++ memory note: The return value must be released.
      * 
      * @return
@@ -3119,19 +3087,17 @@ public abstract class TreeBuilder<T> imp
 
     public final void endTag(ElementName elementName) throws SAXException {
         flushCharacters();
         needToDropLF = false;
         int eltPos;
         int group = elementName.getGroup();
         @Local String name = elementName.name;
         endtagloop: for (;;) {
-            assert !inForeign || currentPtr >= 0 : "In foreign without a root element?";
-            if (inForeign
-                    && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") {
+            if (isInForeign()) {
                 if (errorHandler != null && stack[currentPtr].name != name) {
                     errNoCheck("End tag \u201C"
                             + name
                             + "\u201D did not match the name of the current open element (\u201C"
                             + stack[currentPtr].popName + "\u201D).");
                 }
                 eltPos = currentPtr;
                 for (;;) {
@@ -3436,25 +3402,24 @@ public abstract class TreeBuilder<T> imp
                                         + "\u201D seen but there were unclosed elements.");
                             }
                             removeFromStack(eltPos);
                             break endtagloop;
                         case P:
                             eltPos = findLastInButtonScope("p");
                             if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
                                 err("No \u201Cp\u201D element in scope but a \u201Cp\u201D end tag seen.");
-                                // XXX inline this case
-                                if (inForeign) {
+                                // XXX Can the 'in foreign' case happen anymore?
+                                if (isInForeign()) {
                                     err("HTML start tag \u201C"
                                             + name
                                             + "\u201D in a foreign namespace context.");
                                     while (stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") {
                                         pop();
                                     }
-                                    inForeign = false;
                                 }
                                 appendVoidElementToCurrentMayFoster(
                                         elementName,
                                         HtmlAttributes.EMPTY_ATTRIBUTES);
                                 break endtagloop;
                             }
                             generateImpliedEndTagsExceptFor("p");
                             assert eltPos != TreeBuilder.NOT_FOUND_ON_STACK;
@@ -3531,24 +3496,23 @@ public abstract class TreeBuilder<T> imp
                                 while (currentPtr >= eltPos) {
                                     pop();
                                 }
                                 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
                             }
                             break endtagloop;
                         case BR:
                             err("End tag \u201Cbr\u201D.");
-                            if (inForeign) {
+                            if (isInForeign()) {
                                 err("HTML start tag \u201C"
                                         + name
                                         + "\u201D in a foreign namespace context.");
                                 while (stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") {
                                     pop();
                                 }
-                                inForeign = false;
                             }
                             reconstructTheActiveFormattingElements();
                             appendVoidElementToCurrentMayFoster(
                                     elementName,
                                     HtmlAttributes.EMPTY_ATTRIBUTES);
                             break endtagloop;
                         case AREA_OR_WBR:
                         case PARAM_OR_SOURCE:
@@ -3866,25 +3830,16 @@ public abstract class TreeBuilder<T> imp
                     pop();
                     if (originalMode == AFTER_HEAD) {
                         silentPop();
                     }
                     mode = originalMode;
                     break endtagloop;
             }
         } // endtagloop
-        if (inForeign && !hasForeignInScope()) {
-            /*
-             * If, after doing so, the insertion mode is still "in foreign
-             * content", but there is no element in scope that has a namespace
-             * other than the HTML namespace, switch the insertion mode to the
-             * secondary insertion mode.
-             */
-            inForeign = false;
-        }
     }
 
     private int findLastInTableScopeOrRootTbodyTheadTfoot() {
         for (int i = currentPtr; i > 0; i--) {
             if (stack[i].getGroup() == TreeBuilder.TBODY_OR_THEAD_OR_TFOOT) {
                 return i;
             }
         }
@@ -3950,27 +3905,16 @@ public abstract class TreeBuilder<T> imp
                 return i;
             } else if (stack[i].isScoping()) {
                 return TreeBuilder.NOT_FOUND_ON_STACK;
             }
         }
         return TreeBuilder.NOT_FOUND_ON_STACK;
     }
 
-    private boolean hasForeignInScope() {
-        for (int i = currentPtr; i > 0; i--) {
-            if (stack[i].ns != "http://www.w3.org/1999/xhtml") {
-                return true;
-            } else if (stack[i].isScoping()) {
-                return false;
-            }
-        }
-        return false;
-    }
-
     private void generateImpliedEndTagsExceptFor(@Local String name)
             throws SAXException {
         for (;;) {
             StackNode<T> node = stack[currentPtr];
             switch (node.getGroup()) {
                 case P:
                 case LI:
                 case DD_OR_DT:
@@ -4119,17 +4063,16 @@ public abstract class TreeBuilder<T> imp
 
     private void clearStackBackTo(int eltPos) throws SAXException {
         while (currentPtr > eltPos) { // > not >= intentional
             pop();
         }
     }
 
     private void resetTheInsertionMode() {
-        inForeign = false;
         StackNode<T> node;
         @Local String name;
         @NsUri String ns;
         for (int i = currentPtr; i >= 0; i--) {
             node = stack[i];
             name = node.name;
             ns = node.ns;
             if (i == 0) {
@@ -4158,17 +4101,16 @@ public abstract class TreeBuilder<T> imp
                 return;
             } else if ("colgroup" == name) {
                 mode = IN_COLUMN_GROUP;
                 return;
             } else if ("table" == name) {
                 mode = IN_TABLE;
                 return;
             } else if ("http://www.w3.org/1999/xhtml" != ns) {
-                inForeign = true;
                 mode = framesetOk ? FRAMESET_OK : IN_BODY;
                 return;
             } else if ("head" == name) {
                 mode = framesetOk ? FRAMESET_OK : IN_BODY; // really
                 return;
             } else if ("body" == name) {
                 mode = framesetOk ? FRAMESET_OK : IN_BODY;
                 return;
@@ -5234,18 +5176,22 @@ public abstract class TreeBuilder<T> imp
         this.quirks = false;
     }
 
     // ]NOCPP]
 
     /**
      * @see nu.validator.htmlparser.common.TokenHandler#cdataSectionAllowed()
      */
-    public boolean cdataSectionAllowed() throws SAXException {
-        return inForeign && currentPtr >= 0
+    @Inline public boolean cdataSectionAllowed() throws SAXException {
+        return isInForeign();
+    }
+    
+    private boolean isInForeign() {
+        return currentPtr >= 0
                 && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml";
     }
 
     /**
      * The argument MUST be an interned string or <code>null</code>.
      * 
      * @param context
      */
@@ -5402,34 +5348,33 @@ public abstract class TreeBuilder<T> imp
                         node.name, node.node, node.popName,
                         null);
                 stackCopy[i] = newNode;
             } else {
                 stackCopy[i] = listCopy[listIndex];
                 stackCopy[i].retain();
             }
         }
-        return new StateSnapshot<T>(stackCopy, listCopy, formPointer, headPointer, deepTreeSurrogateParent, mode, originalMode, framesetOk, inForeign, needToDropLF, quirks);
+        return new StateSnapshot<T>(stackCopy, listCopy, formPointer, headPointer, deepTreeSurrogateParent, mode, originalMode, framesetOk, needToDropLF, quirks);
     }
 
     public boolean snapshotMatches(TreeBuilderState<T> snapshot) {
         StackNode<T>[] stackCopy = snapshot.getStack();
         int stackLen = snapshot.getStackLength();
         StackNode<T>[] listCopy = snapshot.getListOfActiveFormattingElements();
         int listLen = snapshot.getListOfActiveFormattingElementsLength();
 
         if (stackLen != currentPtr + 1
                 || listLen != listPtr + 1
                 || formPointer != snapshot.getFormPointer()
                 || headPointer != snapshot.getHeadPointer()
                 || deepTreeSurrogateParent != snapshot.getDeepTreeSurrogateParent()
                 || mode != snapshot.getMode()
                 || originalMode != snapshot.getOriginalMode()
                 || framesetOk != snapshot.isFramesetOk()
-                || inForeign != snapshot.isInForeign()
                 || needToDropLF != snapshot.isNeedToDropLF()
                 || quirks != snapshot.isQuirks()) { // maybe just assert quirks
             return false;
         }
         for (int i = listLen - 1; i >= 0; i--) {
             if (listCopy[i] == null
                     && listOfActiveFormattingElements[i] == null) {
                 continue;
@@ -5503,17 +5448,16 @@ public abstract class TreeBuilder<T> imp
             }
         }
         formPointer = snapshot.getFormPointer();
         headPointer = snapshot.getHeadPointer();
         deepTreeSurrogateParent = snapshot.getDeepTreeSurrogateParent();
         mode = snapshot.getMode();
         originalMode = snapshot.getOriginalMode();
         framesetOk = snapshot.isFramesetOk();
-        inForeign = snapshot.isInForeign();
         needToDropLF = snapshot.isNeedToDropLF();
         quirks = snapshot.isQuirks();
     }
 
     private int findInArray(StackNode<T> node, StackNode<T>[] arr) {
         for (int i = listPtr; i >= 0; i--) {
             if (node == arr[i]) {
                 return i;
@@ -5584,25 +5528,16 @@ public abstract class TreeBuilder<T> imp
      * 
      * @return the framesetOk
      */
     public boolean isFramesetOk() {
         return framesetOk;
     }
     
     /**
-     * Returns the foreignFlag.
-     *
-     * @return the foreignFlag
-     */
-    public boolean isInForeign() {
-        return inForeign;
-    }
-
-    /**
      * Returns the needToDropLF.
      * 
      * @return the needToDropLF
      */
     public boolean isNeedToDropLF() {
         return needToDropLF;
     }
 
--- a/parser/html/nsAHtml5TreeBuilderState.h
+++ b/parser/html/nsAHtml5TreeBuilderState.h
@@ -61,18 +61,16 @@ class nsAHtml5TreeBuilderState {
     virtual nsIContent** getDeepTreeSurrogateParent() = 0;
 
     virtual PRInt32 getMode() = 0;
 
     virtual PRInt32 getOriginalMode() = 0;
 
     virtual PRBool isFramesetOk() = 0;
 
-    virtual PRBool isInForeign() = 0;
-
     virtual PRBool isNeedToDropLF() = 0;
 
     virtual PRBool isQuirks() = 0;
     
     virtual ~nsAHtml5TreeBuilderState() {
     }
 };
 
--- a/parser/html/nsHtml5StateSnapshot.cpp
+++ b/parser/html/nsHtml5StateSnapshot.cpp
@@ -54,26 +54,25 @@
 #include "nsHtml5HtmlAttributes.h"
 #include "nsHtml5StackNode.h"
 #include "nsHtml5UTF16Buffer.h"
 #include "nsHtml5Portability.h"
 
 #include "nsHtml5StateSnapshot.h"
 
 
-nsHtml5StateSnapshot::nsHtml5StateSnapshot(jArray<nsHtml5StackNode*,PRInt32> stack, jArray<nsHtml5StackNode*,PRInt32> listOfActiveFormattingElements, nsIContent** formPointer, nsIContent** headPointer, nsIContent** deepTreeSurrogateParent, PRInt32 mode, PRInt32 originalMode, PRBool framesetOk, PRBool inForeign, PRBool needToDropLF, PRBool quirks)
+nsHtml5StateSnapshot::nsHtml5StateSnapshot(jArray<nsHtml5StackNode*,PRInt32> stack, jArray<nsHtml5StackNode*,PRInt32> listOfActiveFormattingElements, nsIContent** formPointer, nsIContent** headPointer, nsIContent** deepTreeSurrogateParent, PRInt32 mode, PRInt32 originalMode, PRBool framesetOk, PRBool needToDropLF, PRBool quirks)
   : stack(stack),
     listOfActiveFormattingElements(listOfActiveFormattingElements),
     formPointer(formPointer),
     headPointer(headPointer),
     deepTreeSurrogateParent(deepTreeSurrogateParent),
     mode(mode),
     originalMode(originalMode),
     framesetOk(framesetOk),
-    inForeign(inForeign),
     needToDropLF(needToDropLF),
     quirks(quirks)
 {
   MOZ_COUNT_CTOR(nsHtml5StateSnapshot);
 }
 
 jArray<nsHtml5StackNode*,PRInt32> 
 nsHtml5StateSnapshot::getStack()
@@ -119,22 +118,16 @@ nsHtml5StateSnapshot::getOriginalMode()
 
 PRBool 
 nsHtml5StateSnapshot::isFramesetOk()
 {
   return framesetOk;
 }
 
 PRBool 
-nsHtml5StateSnapshot::isInForeign()
-{
-  return inForeign;
-}
-
-PRBool 
 nsHtml5StateSnapshot::isNeedToDropLF()
 {
   return needToDropLF;
 }
 
 PRBool 
 nsHtml5StateSnapshot::isQuirks()
 {
--- a/parser/html/nsHtml5StateSnapshot.h
+++ b/parser/html/nsHtml5StateSnapshot.h
@@ -65,30 +65,28 @@ class nsHtml5StateSnapshot : public nsAH
     autoJArray<nsHtml5StackNode*,PRInt32> stack;
     autoJArray<nsHtml5StackNode*,PRInt32> listOfActiveFormattingElements;
     nsIContent** formPointer;
     nsIContent** headPointer;
     nsIContent** deepTreeSurrogateParent;
     PRInt32 mode;
     PRInt32 originalMode;
     PRBool framesetOk;
-    PRBool inForeign;
     PRBool needToDropLF;
     PRBool quirks;
   public:
-    nsHtml5StateSnapshot(jArray<nsHtml5StackNode*,PRInt32> stack, jArray<nsHtml5StackNode*,PRInt32> listOfActiveFormattingElements, nsIContent** formPointer, nsIContent** headPointer, nsIContent** deepTreeSurrogateParent, PRInt32 mode, PRInt32 originalMode, PRBool framesetOk, PRBool inForeign, PRBool needToDropLF, PRBool quirks);
+    nsHtml5StateSnapshot(jArray<nsHtml5StackNode*,PRInt32> stack, jArray<nsHtml5StackNode*,PRInt32> listOfActiveFormattingElements, nsIContent** formPointer, nsIContent** headPointer, nsIContent** deepTreeSurrogateParent, PRInt32 mode, PRInt32 originalMode, PRBool framesetOk, PRBool needToDropLF, PRBool quirks);
     jArray<nsHtml5StackNode*,PRInt32> getStack();
     jArray<nsHtml5StackNode*,PRInt32> getListOfActiveFormattingElements();
     nsIContent** getFormPointer();
     nsIContent** getHeadPointer();
     nsIContent** getDeepTreeSurrogateParent();
     PRInt32 getMode();
     PRInt32 getOriginalMode();
     PRBool isFramesetOk();
-    PRBool isInForeign();
     PRBool isNeedToDropLF();
     PRBool isQuirks();
     PRInt32 getListOfActiveFormattingElementsLength();
     PRInt32 getStackLength();
     ~nsHtml5StateSnapshot();
     static void initializeStatics();
     static void releaseStatics();
 };
--- a/parser/html/nsHtml5TreeBuilder.cpp
+++ b/parser/html/nsHtml5TreeBuilder.cpp
@@ -106,25 +106,24 @@ nsHtml5TreeBuilder::startTokenization(ns
       tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_SCRIPT_DATA, contextName);
     } else {
       tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_DATA, contextName);
     }
     contextName = nsnull;
     contextNode = nsnull;
   } else {
     mode = NS_HTML5TREE_BUILDER_INITIAL;
-    inForeign = PR_FALSE;
   }
 }
 
 void 
 nsHtml5TreeBuilder::doctype(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier, PRBool forceQuirks)
 {
   needToDropLF = PR_FALSE;
-  if (!inForeign) {
+  if (!isInForeign()) {
     switch(mode) {
       case NS_HTML5TREE_BUILDER_INITIAL: {
         nsString* emptyString = nsHtml5Portability::newEmptyString();
         appendDoctypeToDocument(!name ? nsHtml5Atoms::emptystring : name, !publicIdentifier ? emptyString : publicIdentifier, !systemIdentifier ? emptyString : systemIdentifier);
         nsHtml5Portability::releaseString(emptyString);
         if (isQuirky(name, publicIdentifier, systemIdentifier, forceQuirks)) {
 
           documentModeInternal(QUIRKS_MODE, publicIdentifier, systemIdentifier, PR_FALSE);
@@ -145,17 +144,17 @@ nsHtml5TreeBuilder::doctype(nsIAtom* nam
 
   return;
 }
 
 void 
 nsHtml5TreeBuilder::comment(PRUnichar* buf, PRInt32 start, PRInt32 length)
 {
   needToDropLF = PR_FALSE;
-  if (!inForeign) {
+  if (!isInForeign()) {
     switch(mode) {
       case NS_HTML5TREE_BUILDER_INITIAL:
       case NS_HTML5TREE_BUILDER_BEFORE_HTML:
       case NS_HTML5TREE_BUILDER_AFTER_AFTER_BODY:
       case NS_HTML5TREE_BUILDER_AFTER_AFTER_FRAMESET: {
         appendCommentToDocument(buf, start, length);
         return;
       }
@@ -186,17 +185,17 @@ nsHtml5TreeBuilder::characters(const PRU
       }
     }
     needToDropLF = PR_FALSE;
   }
   switch(mode) {
     case NS_HTML5TREE_BUILDER_IN_BODY:
     case NS_HTML5TREE_BUILDER_IN_CELL:
     case NS_HTML5TREE_BUILDER_IN_CAPTION: {
-      if (!inForeign) {
+      if (!isInForeign()) {
         reconstructTheActiveFormattingElements();
       }
     }
     case NS_HTML5TREE_BUILDER_TEXT: {
       accumulateCharacters(buf, start, length);
       return;
     }
     case NS_HTML5TREE_BUILDER_IN_TABLE:
@@ -232,17 +231,17 @@ nsHtml5TreeBuilder::characters(const PRU
               case NS_HTML5TREE_BUILDER_FRAMESET_OK:
               case NS_HTML5TREE_BUILDER_IN_BODY:
               case NS_HTML5TREE_BUILDER_IN_CELL:
               case NS_HTML5TREE_BUILDER_IN_CAPTION: {
                 if (start < i) {
                   accumulateCharacters(buf, start, i - start);
                   start = i;
                 }
-                if (!inForeign) {
+                if (!isInForeign()) {
                   flushCharacters();
                   reconstructTheActiveFormattingElements();
                 }
                 NS_HTML5_BREAK(charactersloop);
               }
               case NS_HTML5TREE_BUILDER_IN_SELECT:
               case NS_HTML5TREE_BUILDER_IN_SELECT_IN_TABLE: {
                 NS_HTML5_BREAK(charactersloop);
@@ -334,17 +333,17 @@ nsHtml5TreeBuilder::characters(const PRU
               }
               case NS_HTML5TREE_BUILDER_IN_BODY:
               case NS_HTML5TREE_BUILDER_IN_CELL:
               case NS_HTML5TREE_BUILDER_IN_CAPTION: {
                 if (start < i) {
                   accumulateCharacters(buf, start, i - start);
                   start = i;
                 }
-                if (!inForeign) {
+                if (!isInForeign()) {
                   flushCharacters();
                   reconstructTheActiveFormattingElements();
                 }
                 NS_HTML5_BREAK(charactersloop);
               }
               case NS_HTML5TREE_BUILDER_IN_TABLE:
               case NS_HTML5TREE_BUILDER_IN_TABLE_BODY:
               case NS_HTML5TREE_BUILDER_IN_ROW: {
@@ -419,27 +418,27 @@ nsHtml5TreeBuilder::characters(const PRU
       }
     }
   }
 }
 
 void 
 nsHtml5TreeBuilder::zeroOriginatingReplacementCharacter()
 {
-  if (inForeign || mode == NS_HTML5TREE_BUILDER_TEXT) {
+  if (isInForeign() || mode == NS_HTML5TREE_BUILDER_TEXT) {
     characters(REPLACEMENT_CHARACTER, 0, 1);
   }
 }
 
 void 
 nsHtml5TreeBuilder::eof()
 {
   flushCharacters();
   for (; ; ) {
-    if (inForeign) {
+    if (isInForeign()) {
 
       NS_HTML5_BREAK(eofloop);
     }
     switch(mode) {
       case NS_HTML5TREE_BUILDER_INITIAL: {
         documentModeInternal(QUIRKS_MODE, nsnull, nsnull, PR_FALSE);
         mode = NS_HTML5TREE_BUILDER_BEFORE_HTML;
         continue;
@@ -554,26 +553,23 @@ nsHtml5TreeBuilder::endTokenization()
 }
 
 void 
 nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, PRBool selfClosing)
 {
   flushCharacters();
   PRInt32 eltPos;
   needToDropLF = PR_FALSE;
-  PRBool needsPostProcessing = PR_FALSE;
   starttagloop: for (; ; ) {
     PRInt32 group = elementName->getGroup();
     nsIAtom* name = elementName->name;
-    if (inForeign) {
+    if (isInForeign()) {
       nsHtml5StackNode* currentNode = stack[currentPtr];
       PRInt32 currNs = currentNode->ns;
-      if ((kNameSpaceID_XHTML == currNs) || currentNode->isHtmlIntegrationPoint() || (currNs == kNameSpaceID_MathML && ((currentNode->getGroup() == NS_HTML5TREE_BUILDER_MI_MO_MN_MS_MTEXT && group != NS_HTML5TREE_BUILDER_MGLYPH_OR_MALIGNMARK) || (currentNode->getGroup() == NS_HTML5TREE_BUILDER_ANNOTATION_XML && group == NS_HTML5TREE_BUILDER_SVG)))) {
-        needsPostProcessing = PR_TRUE;
-      } else {
+      if (!(currentNode->isHtmlIntegrationPoint() || (currNs == kNameSpaceID_MathML && ((currentNode->getGroup() == NS_HTML5TREE_BUILDER_MI_MO_MN_MS_MTEXT && group != NS_HTML5TREE_BUILDER_MGLYPH_OR_MALIGNMARK) || (currentNode->getGroup() == NS_HTML5TREE_BUILDER_ANNOTATION_XML && group == NS_HTML5TREE_BUILDER_SVG))))) {
         switch(group) {
           case NS_HTML5TREE_BUILDER_B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
           case NS_HTML5TREE_BUILDER_DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
           case NS_HTML5TREE_BUILDER_BODY:
           case NS_HTML5TREE_BUILDER_BR:
           case NS_HTML5TREE_BUILDER_RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR:
           case NS_HTML5TREE_BUILDER_DD_OR_DT:
           case NS_HTML5TREE_BUILDER_UL_OR_OL_OR_DL:
@@ -586,30 +582,24 @@ nsHtml5TreeBuilder::startTag(nsHtml5Elem
           case NS_HTML5TREE_BUILDER_NOBR:
           case NS_HTML5TREE_BUILDER_P:
           case NS_HTML5TREE_BUILDER_PRE_OR_LISTING:
           case NS_HTML5TREE_BUILDER_TABLE: {
 
             while (!isSpecialParentInForeign(stack[currentPtr])) {
               pop();
             }
-            if (!hasForeignInScope()) {
-              inForeign = PR_FALSE;
-            }
             NS_HTML5_CONTINUE(starttagloop);
           }
           case NS_HTML5TREE_BUILDER_FONT: {
             if (attributes->contains(nsHtml5AttributeName::ATTR_COLOR) || attributes->contains(nsHtml5AttributeName::ATTR_FACE) || attributes->contains(nsHtml5AttributeName::ATTR_SIZE)) {
 
               while (!isSpecialParentInForeign(stack[currentPtr])) {
                 pop();
               }
-              if (!hasForeignInScope()) {
-                inForeign = PR_FALSE;
-              }
               NS_HTML5_CONTINUE(starttagloop);
             }
           }
           default: {
             if (kNameSpaceID_SVG == currNs) {
               attributes->adjustForSvg();
               if (selfClosing) {
                 appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
@@ -1245,30 +1235,28 @@ nsHtml5TreeBuilder::startTag(nsHtml5Elem
             case NS_HTML5TREE_BUILDER_MATH: {
               reconstructTheActiveFormattingElements();
               attributes->adjustForMath();
               if (selfClosing) {
                 appendVoidElementToCurrentMayFosterMathML(elementName, attributes);
                 selfClosing = PR_FALSE;
               } else {
                 appendToCurrentNodeAndPushElementMayFosterMathML(elementName, attributes);
-                inForeign = PR_TRUE;
               }
               attributes = nsnull;
               NS_HTML5_BREAK(starttagloop);
             }
             case NS_HTML5TREE_BUILDER_SVG: {
               reconstructTheActiveFormattingElements();
               attributes->adjustForSvg();
               if (selfClosing) {
                 appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
                 selfClosing = PR_FALSE;
               } else {
                 appendToCurrentNodeAndPushElementMayFosterSVG(elementName, attributes);
-                inForeign = PR_TRUE;
               }
               attributes = nsnull;
               NS_HTML5_BREAK(starttagloop);
             }
             case NS_HTML5TREE_BUILDER_CAPTION:
             case NS_HTML5TREE_BUILDER_COL:
             case NS_HTML5TREE_BUILDER_COLGROUP:
             case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT:
@@ -1787,37 +1775,27 @@ nsHtml5TreeBuilder::startTag(nsHtml5Elem
       }
       case NS_HTML5TREE_BUILDER_TEXT: {
 
         NS_HTML5_BREAK(starttagloop);
       }
     }
   }
   starttagloop_end: ;
-  if (needsPostProcessing && inForeign && !hasForeignInScope()) {
-    inForeign = PR_FALSE;
-  }
 
   if (attributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
     delete attributes;
   }
 }
 
 PRBool 
 nsHtml5TreeBuilder::isSpecialParentInForeign(nsHtml5StackNode* stackNode)
 {
   PRInt32 ns = stackNode->ns;
-  if (kNameSpaceID_XHTML == ns) {
-    return PR_TRUE;
-  }
-  if (ns == kNameSpaceID_SVG) {
-    return stackNode->getGroup() == NS_HTML5TREE_BUILDER_FOREIGNOBJECT_OR_DESC || stackNode->getGroup() == NS_HTML5TREE_BUILDER_TITLE;
-  }
-
-  return stackNode->getGroup() == NS_HTML5TREE_BUILDER_MI_MO_MN_MS_MTEXT;
+  return (kNameSpaceID_XHTML == ns) || (stackNode->isHtmlIntegrationPoint()) || ((kNameSpaceID_MathML == ns) && (stackNode->getGroup() == NS_HTML5TREE_BUILDER_MI_MO_MN_MS_MTEXT));
 }
 
 nsString* 
 nsHtml5TreeBuilder::extractCharsetFromContent(nsString* attributeValue)
 {
   PRInt32 charsetState = NS_HTML5TREE_BUILDER_CHARSET_INITIAL;
   PRInt32 start = -1;
   PRInt32 end = -1;
@@ -2040,18 +2018,17 @@ void
 nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName)
 {
   flushCharacters();
   needToDropLF = PR_FALSE;
   PRInt32 eltPos;
   PRInt32 group = elementName->getGroup();
   nsIAtom* name = elementName->name;
   for (; ; ) {
-
-    if (inForeign && stack[currentPtr]->ns != kNameSpaceID_XHTML) {
+    if (isInForeign()) {
 
       eltPos = currentPtr;
       for (; ; ) {
         if (stack[eltPos]->name == name) {
           while (currentPtr >= eltPos) {
             pop();
           }
           NS_HTML5_BREAK(endtagloop);
@@ -2325,22 +2302,21 @@ nsHtml5TreeBuilder::endTag(nsHtml5Elemen
 
             removeFromStack(eltPos);
             NS_HTML5_BREAK(endtagloop);
           }
           case NS_HTML5TREE_BUILDER_P: {
             eltPos = findLastInButtonScope(nsHtml5Atoms::p);
             if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
 
-              if (inForeign) {
+              if (isInForeign()) {
 
                 while (stack[currentPtr]->ns != kNameSpaceID_XHTML) {
                   pop();
                 }
-                inForeign = PR_FALSE;
               }
               appendVoidElementToCurrentMayFoster(elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
               NS_HTML5_BREAK(endtagloop);
             }
             generateImpliedEndTagsExceptFor(nsHtml5Atoms::p);
 
 
             while (currentPtr >= eltPos) {
@@ -2391,22 +2367,21 @@ nsHtml5TreeBuilder::endTag(nsHtml5Elemen
                 pop();
               }
               clearTheListOfActiveFormattingElementsUpToTheLastMarker();
             }
             NS_HTML5_BREAK(endtagloop);
           }
           case NS_HTML5TREE_BUILDER_BR: {
 
-            if (inForeign) {
+            if (isInForeign()) {
 
               while (stack[currentPtr]->ns != kNameSpaceID_XHTML) {
                 pop();
               }
-              inForeign = PR_FALSE;
             }
             reconstructTheActiveFormattingElements();
             appendVoidElementToCurrentMayFoster(elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
             NS_HTML5_BREAK(endtagloop);
           }
           case NS_HTML5TREE_BUILDER_AREA_OR_WBR:
           case NS_HTML5TREE_BUILDER_PARAM_OR_SOURCE:
           case NS_HTML5TREE_BUILDER_EMBED_OR_IMG:
@@ -2714,19 +2689,16 @@ nsHtml5TreeBuilder::endTag(nsHtml5Elemen
           silentPop();
         }
         mode = originalMode;
         NS_HTML5_BREAK(endtagloop);
       }
     }
   }
   endtagloop_end: ;
-  if (inForeign && !hasForeignInScope()) {
-    inForeign = PR_FALSE;
-  }
 }
 
 PRInt32 
 nsHtml5TreeBuilder::findLastInTableScopeOrRootTbodyTheadTfoot()
 {
   for (PRInt32 i = currentPtr; i > 0; i--) {
     if (stack[i]->getGroup() == NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT) {
       return i;
@@ -2806,29 +2778,16 @@ nsHtml5TreeBuilder::findLastInScopeHn()
       return i;
     } else if (stack[i]->isScoping()) {
       return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
     }
   }
   return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
 }
 
-PRBool 
-nsHtml5TreeBuilder::hasForeignInScope()
-{
-  for (PRInt32 i = currentPtr; i > 0; i--) {
-    if (stack[i]->ns != kNameSpaceID_XHTML) {
-      return PR_TRUE;
-    } else if (stack[i]->isScoping()) {
-      return PR_FALSE;
-    }
-  }
-  return PR_FALSE;
-}
-
 void 
 nsHtml5TreeBuilder::generateImpliedEndTagsExceptFor(nsIAtom* name)
 {
   for (; ; ) {
     nsHtml5StackNode* node = stack[currentPtr];
     switch(node->getGroup()) {
       case NS_HTML5TREE_BUILDER_P:
       case NS_HTML5TREE_BUILDER_LI:
@@ -2969,17 +2928,16 @@ nsHtml5TreeBuilder::clearStackBackTo(PRI
   while (currentPtr > eltPos) {
     pop();
   }
 }
 
 void 
 nsHtml5TreeBuilder::resetTheInsertionMode()
 {
-  inForeign = PR_FALSE;
   nsHtml5StackNode* node;
   nsIAtom* name;
   PRInt32 ns;
   for (PRInt32 i = currentPtr; i >= 0; i--) {
     node = stack[i];
     name = node->name;
     ns = node->ns;
     if (!i) {
@@ -3008,17 +2966,16 @@ nsHtml5TreeBuilder::resetTheInsertionMod
       return;
     } else if (nsHtml5Atoms::colgroup == name) {
       mode = NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP;
       return;
     } else if (nsHtml5Atoms::table == name) {
       mode = NS_HTML5TREE_BUILDER_IN_TABLE;
       return;
     } else if (kNameSpaceID_XHTML != ns) {
-      inForeign = PR_TRUE;
       mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
       return;
     } else if (nsHtml5Atoms::head == name) {
       mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
       return;
     } else if (nsHtml5Atoms::body == name) {
       mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
       return;
@@ -3741,19 +3698,19 @@ nsHtml5TreeBuilder::appendVoidFormToCurr
 
 void 
 nsHtml5TreeBuilder::requestSuspension()
 {
   tokenizer->requestSuspension();
 }
 
 PRBool 
-nsHtml5TreeBuilder::cdataSectionAllowed()
+nsHtml5TreeBuilder::isInForeign()
 {
-  return inForeign && currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML;
+  return currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML;
 }
 
 void 
 nsHtml5TreeBuilder::setFragmentContext(nsIAtom* context, PRInt32 ns, nsIContent** node, PRBool quirks)
 {
   this->contextName = context;
   this->contextNamespace = ns;
   this->contextNode = node;
@@ -3848,27 +3805,27 @@ nsHtml5TreeBuilder::newSnapshot()
     if (listIndex == -1) {
       nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, node->name, node->node, node->popName, nsnull);
       stackCopy[i] = newNode;
     } else {
       stackCopy[i] = listCopy[listIndex];
       stackCopy[i]->retain();
     }
   }
-  return new nsHtml5StateSnapshot(stackCopy, listCopy, formPointer, headPointer, deepTreeSurrogateParent, mode, originalMode, framesetOk, inForeign, needToDropLF, quirks);
+  return new nsHtml5StateSnapshot(stackCopy, listCopy, formPointer, headPointer, deepTreeSurrogateParent, mode, originalMode, framesetOk, needToDropLF, quirks);
 }
 
 PRBool 
 nsHtml5TreeBuilder::snapshotMatches(nsAHtml5TreeBuilderState* snapshot)
 {
   jArray<nsHtml5StackNode*,PRInt32> stackCopy = snapshot->getStack();
   PRInt32 stackLen = snapshot->getStackLength();
   jArray<nsHtml5StackNode*,PRInt32> listCopy = snapshot->getListOfActiveFormattingElements();
   PRInt32 listLen = snapshot->getListOfActiveFormattingElementsLength();
-  if (stackLen != currentPtr + 1 || listLen != listPtr + 1 || formPointer != snapshot->getFormPointer() || headPointer != snapshot->getHeadPointer() || deepTreeSurrogateParent != snapshot->getDeepTreeSurrogateParent() || mode != snapshot->getMode() || originalMode != snapshot->getOriginalMode() || framesetOk != snapshot->isFramesetOk() || inForeign != snapshot->isInForeign() || needToDropLF != snapshot->isNeedToDropLF() || quirks != snapshot->isQuirks()) {
+  if (stackLen != currentPtr + 1 || listLen != listPtr + 1 || formPointer != snapshot->getFormPointer() || headPointer != snapshot->getHeadPointer() || deepTreeSurrogateParent != snapshot->getDeepTreeSurrogateParent() || mode != snapshot->getMode() || originalMode != snapshot->getOriginalMode() || framesetOk != snapshot->isFramesetOk() || needToDropLF != snapshot->isNeedToDropLF() || quirks != snapshot->isQuirks()) {
     return PR_FALSE;
   }
   for (PRInt32 i = listLen - 1; i >= 0; i--) {
     if (!listCopy[i] && !listOfActiveFormattingElements[i]) {
       continue;
     } else if (!listCopy[i] || !listOfActiveFormattingElements[i]) {
       return PR_FALSE;
     }
@@ -3928,17 +3885,16 @@ nsHtml5TreeBuilder::loadState(nsAHtml5Tr
     }
   }
   formPointer = snapshot->getFormPointer();
   headPointer = snapshot->getHeadPointer();
   deepTreeSurrogateParent = snapshot->getDeepTreeSurrogateParent();
   mode = snapshot->getMode();
   originalMode = snapshot->getOriginalMode();
   framesetOk = snapshot->isFramesetOk();
-  inForeign = snapshot->isInForeign();
   needToDropLF = snapshot->isNeedToDropLF();
   quirks = snapshot->isQuirks();
 }
 
 PRInt32 
 nsHtml5TreeBuilder::findInArray(nsHtml5StackNode* node, jArray<nsHtml5StackNode*,PRInt32> arr)
 {
   for (PRInt32 i = listPtr; i >= 0; i--) {
@@ -3993,22 +3949,16 @@ nsHtml5TreeBuilder::getOriginalMode()
 
 PRBool 
 nsHtml5TreeBuilder::isFramesetOk()
 {
   return framesetOk;
 }
 
 PRBool 
-nsHtml5TreeBuilder::isInForeign()
-{
-  return inForeign;
-}
-
-PRBool 
 nsHtml5TreeBuilder::isNeedToDropLF()
 {
   return needToDropLF;
 }
 
 PRBool 
 nsHtml5TreeBuilder::isQuirks()
 {
--- a/parser/html/nsHtml5TreeBuilder.h
+++ b/parser/html/nsHtml5TreeBuilder.h
@@ -69,17 +69,16 @@ class nsHtml5Portability;
 class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState
 {
   private:
     static PRUnichar REPLACEMENT_CHARACTER[];
     static staticJArray<const char*,PRInt32> QUIRKY_PUBLIC_IDS;
     PRInt32 mode;
     PRInt32 originalMode;
     PRBool framesetOk;
-    PRBool inForeign;
   protected:
     nsHtml5Tokenizer* tokenizer;
   private:
     PRBool scriptingEnabled;
     PRBool needToDropLF;
     PRBool fragment;
     nsIAtom* contextName;
     PRInt32 contextNamespace;
@@ -116,17 +115,16 @@ class nsHtml5TreeBuilder : public nsAHtm
   private:
     PRInt32 findLastInTableScopeOrRootTbodyTheadTfoot();
     PRInt32 findLast(nsIAtom* name);
     PRInt32 findLastInTableScope(nsIAtom* name);
     PRInt32 findLastInButtonScope(nsIAtom* name);
     PRInt32 findLastInScope(nsIAtom* name);
     PRInt32 findLastInListScope(nsIAtom* name);
     PRInt32 findLastInScopeHn();
-    PRBool hasForeignInScope();
     void generateImpliedEndTagsExceptFor(nsIAtom* name);
     void generateImpliedEndTags();
     PRBool isSecondOnStackBody();
     void documentModeInternal(nsHtml5DocumentMode m, nsString* publicIdentifier, nsString* systemIdentifier, PRBool html4SpecificAdditionalErrorChecks);
     PRBool isAlmostStandards(nsString* publicIdentifier, nsString* systemIdentifier);
     PRBool isQuirky(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier, PRBool forceQuirks);
     void closeTheCell(PRInt32 eltPos);
     PRInt32 findLastInTableScopeTdTh();
@@ -207,17 +205,24 @@ class nsHtml5TreeBuilder : public nsAHtm
     void addAttributesToElement(nsIContent** element, nsHtml5HtmlAttributes* attributes);
     void markMalformedIfScript(nsIContent** elt);
     void start(PRBool fragmentMode);
     void end();
     void appendDoctypeToDocument(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier);
     void elementPushed(PRInt32 ns, nsIAtom* name, nsIContent** node);
     void elementPopped(PRInt32 ns, nsIAtom* name, nsIContent** node);
   public:
-    PRBool cdataSectionAllowed();
+    inline PRBool cdataSectionAllowed()
+    {
+      return isInForeign();
+    }
+
+  private:
+    PRBool isInForeign();
+  public:
     void setFragmentContext(nsIAtom* context, PRInt32 ns, nsIContent** node, PRBool quirks);
   protected:
     nsIContent** currentNode();
   public:
     PRBool isScriptingEnabled();
     void setScriptingEnabled(PRBool scriptingEnabled);
     void flushCharacters();
   private:
@@ -232,17 +237,16 @@ class nsHtml5TreeBuilder : public nsAHtm
     nsIContent** getFormPointer();
     nsIContent** getHeadPointer();
     nsIContent** getDeepTreeSurrogateParent();
     jArray<nsHtml5StackNode*,PRInt32> getListOfActiveFormattingElements();
     jArray<nsHtml5StackNode*,PRInt32> getStack();
     PRInt32 getMode();
     PRInt32 getOriginalMode();
     PRBool isFramesetOk();
-    PRBool isInForeign();
     PRBool isNeedToDropLF();
     PRBool isQuirks();
     PRInt32 getListOfActiveFormattingElementsLength();
     PRInt32 getStackLength();
     static void initializeStatics();
     static void releaseStatics();
 
 #include "nsHtml5TreeBuilderHSupplement.h"
--- a/parser/htmlparser/tests/mochitest/html5_tree_construction_exceptions.js
+++ b/parser/htmlparser/tests/mochitest/html5_tree_construction_exceptions.js
@@ -2,16 +2,15 @@
  * These are the tests we don't pass. The test data comes from the .dat
  * files under html5lib_tree_construction/. Please see
  * html5lib_tree_construction/html5lib_license.txt for the license for these
  * tests.
  */
 var html5Exceptions = {
   "<!doctype html><keygen><frameset>" : true, // Bug 101019
   "<select><keygen>" : true, // Bug 101019
-  "<math><mi><div><object><div><span></span></div></object></div></mi><mi>" : true, // Bug 606925
   "<plaintext>\u0000filler\u0000text\u0000" : true, // Bug 612527
   "<body><svg><foreignObject>\u0000filler\u0000text" : true, // Bug 612527
   "<svg>\u0000</svg><frameset>" : true, // Bug 612527
   "<svg>\u0000 </svg><frameset>" : true, // Bug 612527
   "<option><span><option>" : true, // Bug 612528
   "<!doctype html><div><body><frameset>" : true, // Bug 614241
 }