Bug 1091425 - Use the correct document when creating nodes in the HTML5 parser. r=hsivonen
authorWilliam Chen <wchen@mozilla.com>
Sun, 09 Nov 2014 22:50:18 -0800
changeset 226150 ede99651d08916849d4b28ef3b4c51c09787d7a1
parent 226149 42078caf21b7ef1165369cbdcdb57526e2c498cc
child 226151 0da722f1ddadae22f43b24ec7049055e104de000
push id36
push userdburns@mozilla.com
push dateMon, 10 Nov 2014 15:14:02 +0000
reviewershsivonen
bugs1091425
milestone36.0a1
Bug 1091425 - Use the correct document when creating nodes in the HTML5 parser. r=hsivonen
dom/tests/mochitest/webcomponents/mochitest.ini
dom/tests/mochitest/webcomponents/test_template_custom_elements.html
parser/html/javasrc/TreeBuilder.java
parser/html/nsHtml5Highlighter.cpp
parser/html/nsHtml5Highlighter.h
parser/html/nsHtml5TreeBuilder.cpp
parser/html/nsHtml5TreeBuilder.h
parser/html/nsHtml5TreeBuilderCppSupplement.h
parser/html/nsHtml5TreeOperation.cpp
parser/html/nsHtml5TreeOperation.h
--- a/dom/tests/mochitest/webcomponents/mochitest.ini
+++ b/dom/tests/mochitest/webcomponents/mochitest.ini
@@ -17,16 +17,17 @@ support-files =
 [test_document_register_parser.html]
 [test_document_register_stack.html]
 [test_document_shared_registry.html]
 [test_event_dispatch.html]
 [test_event_retarget.html]
 [test_event_stopping.html]
 [test_template.html]
 [test_template_xhtml.html]
+[test_template_custom_elements.html]
 [test_shadowroot.html]
 [test_shadowroot_inert_element.html]
 [test_shadowroot_host.html]
 [test_shadowroot_style.html]
 [test_shadowroot_style_multiple_shadow.html]
 [test_shadowroot_style_order.html]
 [test_shadowroot_youngershadowroot.html]
 [test_style_fallback_content.html]
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_template_custom_elements.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1091425
+-->
+<head>
+  <title>Test for custom elements in template</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<template>
+  <x-foo></x-foo>
+</template>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1091425">Bug 1091425</a>
+<script>
+
+var p = {};
+p.createdCallback = function() {
+  ok(false, "Created callback should not be called for custom elements in templates.");
+};
+
+document.registerElement("x-foo", { prototype: p });
+
+ok(true, "Created callback should not be called for custom elements in templates.");
+
+</script>
+<template>
+  <x-foo></x-foo>
+</template>
+</body>
+</html>
--- a/parser/html/javasrc/TreeBuilder.java
+++ b/parser/html/javasrc/TreeBuilder.java
@@ -714,17 +714,17 @@ public abstract class TreeBuilder<T> imp
             contextNode = null;
         } else {
             mode = INITIAL;
             // If we are viewing XML source, put a foreign element permanently
             // on the stack so that cdataSectionAllowed() returns true.
             // CPPONLY: if (tokenizer.isViewingXmlSource()) {
             // CPPONLY: T elt = createElement("http://www.w3.org/2000/svg",
             // CPPONLY: "svg",
-            // CPPONLY: tokenizer.emptyAttributes());
+            // CPPONLY: tokenizer.emptyAttributes(), null);
             // CPPONLY: StackNode<T> node = new StackNode<T>(ElementName.SVG,
             // CPPONLY: "svg",
             // CPPONLY: elt);
             // CPPONLY: currentPtr++;
             // CPPONLY: stack[currentPtr] = node;
             // CPPONLY: }
         }
     }
@@ -4801,17 +4801,17 @@ public abstract class TreeBuilder<T> imp
                 // now node is both on stack and in the list
                 if (nodePos == furthestBlockPos) {
                     bookmark = nodeListPos + 1;
                 }
                 // if (hasChildren(node.node)) { XXX AAA CHANGE
                 assert node == listOfActiveFormattingElements[nodeListPos];
                 assert node == stack[nodePos];
                 T clone = createElement("http://www.w3.org/1999/xhtml",
-                        node.name, node.attributes.cloneAttributes(null));
+                        node.name, node.attributes.cloneAttributes(null), commonAncestor.node);
                 StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
                         node.name, clone, node.popName, node.attributes
                         // [NOCPP[
                         , node.getLocator()
                         // ]NOCPP]
                 ); // creation ownership goes to stack
                 node.dropAttributes(); // adopt ownership to newNode
                 stack[nodePos] = newNode;
@@ -4830,17 +4830,17 @@ public abstract class TreeBuilder<T> imp
                 detachFromParent(lastNode.node);
                 insertIntoFosterParent(lastNode.node);
             } else {
                 detachFromParent(lastNode.node);
                 appendElement(lastNode.node, commonAncestor.node);
             }
             T clone = createElement("http://www.w3.org/1999/xhtml",
                     formattingElt.name,
-                    formattingElt.attributes.cloneAttributes(null));
+                    formattingElt.attributes.cloneAttributes(null), furthestBlock.node);
             StackNode<T> formattingClone = new StackNode<T>(
                     formattingElt.getFlags(), formattingElt.ns,
                     formattingElt.name, clone, formattingElt.popName,
                     formattingElt.attributes
                     // [NOCPP[
                     , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
                     // ]NOCPP]
             ); // Ownership transfers to stack below
@@ -5009,32 +5009,38 @@ public abstract class TreeBuilder<T> imp
             }
             if (isInStack(listOfActiveFormattingElements[entryPos])) {
                 break;
             }
         }
         while (entryPos < listPtr) {
             entryPos++;
             StackNode<T> entry = listOfActiveFormattingElements[entryPos];
-            T clone = createElement("http://www.w3.org/1999/xhtml", entry.name,
-                    entry.attributes.cloneAttributes(null));
+            StackNode<T> currentNode = stack[currentPtr];
+
+            T clone;
+            if (currentNode.isFosterParenting()) {
+                clone = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", entry.name,
+                        entry.attributes.cloneAttributes(null));
+            } else {
+                clone = createElement("http://www.w3.org/1999/xhtml", entry.name,
+                        entry.attributes.cloneAttributes(null), currentNode.node);
+                appendElement(clone, currentNode.node);
+            }
+
             StackNode<T> entryClone = new StackNode<T>(entry.getFlags(),
                     entry.ns, entry.name, clone, entry.popName,
                     entry.attributes
                     // [NOCPP[
                     , entry.getLocator()
-            // ]NOCPP]
+                    // ]NOCPP]
             );
+
             entry.dropAttributes(); // transfer ownership to entryClone
-            StackNode<T> currentNode = stack[currentPtr];
-            if (currentNode.isFosterParenting()) {
-                insertIntoFosterParent(clone);
-            } else {
-                appendElement(clone, currentNode.node);
-            }
+
             push(entryClone);
             // stack takes ownership of the local variable
             listOfActiveFormattingElements[entryPos] = entryClone;
             // overwriting the old entry on the list, so release & retain
             entry.release();
             entryClone.retain();
         }
     }
@@ -5047,16 +5053,36 @@ public abstract class TreeBuilder<T> imp
             appendElement(child, stack[templatePos].node);
             return;
         }
 
         StackNode<T> node = stack[tablePos];
         insertFosterParentedChild(child, node.node, stack[tablePos - 1].node);
     }
 
+    private T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
+            HtmlAttributes attributes) throws SAXException {
+        return createAndInsertFosterParentedElement(ns, name, attributes, null);
+    }
+
+    private T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
+            HtmlAttributes attributes, T form) throws SAXException {
+        int tablePos = findLastOrRoot(TreeBuilder.TABLE);
+        int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE);
+
+        if (templatePos >= tablePos) {
+            T child = createElement(ns, name, attributes, form, stack[templatePos].node);
+            appendElement(child, stack[templatePos].node);
+            return child;
+        }
+
+        StackNode<T> node = stack[tablePos];
+        return createAndInsertFosterParentedElement(ns, name, attributes, form, node.node, stack[tablePos - 1].node);
+    }
+
     private boolean isInStack(StackNode<T> node) {
         for (int i = currentPtr; i >= 0; i--) {
             if (stack[i] == node) {
                 return true;
             }
         }
         return false;
     }
@@ -5201,19 +5227,19 @@ public abstract class TreeBuilder<T> imp
         appendHtmlElementToDocumentAndPush(tokenizer.emptyAttributes());
     }
 
     private void appendToCurrentNodeAndPushHeadElement(HtmlAttributes attributes)
             throws SAXException {
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         // ]NOCPP]
-        T elt = createElement("http://www.w3.org/1999/xhtml", "head",
-                attributes);
-        appendElement(elt, stack[currentPtr].node);
+        T currentNode = stack[currentPtr].node;
+        T elt = createElement("http://www.w3.org/1999/xhtml", "head", attributes, currentNode);
+        appendElement(elt, currentNode);
         headPointer = elt;
         StackNode<T> node = new StackNode<T>(ElementName.HEAD,
                 elt
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
@@ -5229,55 +5255,57 @@ public abstract class TreeBuilder<T> imp
         appendToCurrentNodeAndPushBodyElement(tokenizer.emptyAttributes());
     }
 
     private void appendToCurrentNodeAndPushFormElementMayFoster(
             HtmlAttributes attributes) throws SAXException {
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         // ]NOCPP]
-        T elt = createElement("http://www.w3.org/1999/xhtml", "form",
-                attributes);
+
+        T elt;
+        StackNode<T> current = stack[currentPtr];
+        if (current.isFosterParenting()) {
+            fatal();
+            elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", "form", attributes);
+        } else {
+            elt = createElement("http://www.w3.org/1999/xhtml", "form", attributes, current.node);
+            appendElement(elt, current.node);
+        }
 
         if (!isTemplateContents()) {
             formPointer = elt;
         }
 
-        StackNode<T> current = stack[currentPtr];
-        if (current.isFosterParenting()) {
-            fatal();
-            insertIntoFosterParent(elt);
-        } else {
-            appendElement(elt, current.node);
-        }
         StackNode<T> node = new StackNode<T>(ElementName.FORM,
                 elt
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
-        // ]NOCPP]
+                // ]NOCPP]
         );
         push(node);
     }
 
     private void appendToCurrentNodeAndPushFormattingElementMayFoster(
             ElementName elementName, HtmlAttributes attributes)
             throws SAXException {
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         // ]NOCPP]
         // This method can't be called for custom elements
         HtmlAttributes clone = attributes.cloneAttributes(null);
         // Attributes must not be read after calling createElement, because
         // createElement may delete attributes in C++.
-        T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes);
+        T elt;
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
-            insertIntoFosterParent(elt);
+            elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.name, attributes);
         } else {
+            elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, current.node);
             appendElement(elt, current.node);
         }
         StackNode<T> node = new StackNode<T>(elementName, elt, clone
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
@@ -5287,18 +5315,19 @@ public abstract class TreeBuilder<T> imp
 
     private void appendToCurrentNodeAndPushElement(ElementName elementName,
             HtmlAttributes attributes)
             throws SAXException {
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         // ]NOCPP]
         // This method can't be called for custom elements
-        T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes);
-        appendElement(elt, stack[currentPtr].node);
+        T currentNode = stack[currentPtr].node;
+        T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, currentNode);
+        appendElement(elt, currentNode);
         if (ElementName.TEMPLATE == elementName) {
             elt = getDocumentFragmentForTemplate(elt);
         }
         StackNode<T> node = new StackNode<T>(elementName, elt
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
@@ -5310,22 +5339,23 @@ public abstract class TreeBuilder<T> imp
             throws SAXException {
         @Local String popName = elementName.name;
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         if (elementName.isCustom()) {
             popName = checkPopName(popName);
         }
         // ]NOCPP]
-        T elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes);
+        T elt;
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
-            insertIntoFosterParent(elt);
+            elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes);
         } else {
+            elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node);
             appendElement(elt, current.node);
         }
         StackNode<T> node = new StackNode<T>(elementName, elt, popName
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
@@ -5343,23 +5373,23 @@ public abstract class TreeBuilder<T> imp
         // ]NOCPP]
         boolean markAsHtmlIntegrationPoint = false;
         if (ElementName.ANNOTATION_XML == elementName
                 && annotationXmlEncodingPermitsHtml(attributes)) {
             markAsHtmlIntegrationPoint = true;
         }
         // Attributes must not be read after calling createElement(), since
         // createElement may delete the object in C++.
-        T elt = createElement("http://www.w3.org/1998/Math/MathML", popName,
-                attributes);
+        T elt;
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
-            insertIntoFosterParent(elt);
+            elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes);
         } else {
+            elt  = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node);
             appendElement(elt, current.node);
         }
         StackNode<T> node = new StackNode<T>(elementName, elt, popName,
                 markAsHtmlIntegrationPoint
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
@@ -5392,22 +5422,23 @@ public abstract class TreeBuilder<T> imp
             throws SAXException {
         @Local String popName = elementName.camelCaseName;
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/2000/svg");
         if (elementName.isCustom()) {
             popName = checkPopName(popName);
         }
         // ]NOCPP]
-        T elt = createElement("http://www.w3.org/2000/svg", popName, attributes);
+        T elt;
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
-            insertIntoFosterParent(elt);
+            elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes);
         } else {
+            elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node);
             appendElement(elt, current.node);
         }
         StackNode<T> node = new StackNode<T>(elementName, popName, elt
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
@@ -5415,142 +5446,151 @@ public abstract class TreeBuilder<T> imp
 
     private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName,
             HtmlAttributes attributes, T form)
             throws SAXException {
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         // ]NOCPP]
         // Can't be called for custom elements
-        T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes,
-                form == null || fragment || isTemplateContents() ? null : form);
+        T elt;
+        T formOwner = form == null || fragment || isTemplateContents() ? null : form;
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
-            insertIntoFosterParent(elt);
+            elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.name,
+                    attributes, formOwner);
         } else {
+            elt = createElement("http://www.w3.org/1999/xhtml", elementName.name,
+                    attributes, formOwner, current.node);
             appendElement(elt, current.node);
         }
         StackNode<T> node = new StackNode<T>(elementName, elt
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
     }
 
     private void appendVoidElementToCurrentMayFoster(
             @Local String name, HtmlAttributes attributes, T form) throws SAXException {
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         // ]NOCPP]
         // Can't be called for custom elements
-        T elt = createElement("http://www.w3.org/1999/xhtml", name, attributes,
-                form == null || fragment || isTemplateContents() ? null : form);
+        T elt;
+        T formOwner = form == null || fragment || isTemplateContents() ? null : form;
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
-            insertIntoFosterParent(elt);
+            elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", name,
+                    attributes, formOwner);
         } else {
+            elt = createElement("http://www.w3.org/1999/xhtml", name,
+                    attributes, formOwner, current.node);
             appendElement(elt, current.node);
         }
         elementPushed("http://www.w3.org/1999/xhtml", name, elt);
         elementPopped("http://www.w3.org/1999/xhtml", name, elt);
     }
 
     private void appendVoidElementToCurrentMayFoster(
             ElementName elementName, HtmlAttributes attributes)
             throws SAXException {
         @Local String popName = elementName.name;
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         if (elementName.isCustom()) {
             popName = checkPopName(popName);
         }
         // ]NOCPP]
-        T elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes);
+        T elt;
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
-            insertIntoFosterParent(elt);
+            elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes);
         } else {
+            elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node);
             appendElement(elt, current.node);
         }
         elementPushed("http://www.w3.org/1999/xhtml", popName, elt);
         elementPopped("http://www.w3.org/1999/xhtml", popName, elt);
     }
 
     private void appendVoidElementToCurrentMayFosterSVG(
             ElementName elementName, HtmlAttributes attributes)
             throws SAXException {
         @Local String popName = elementName.camelCaseName;
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/2000/svg");
         if (elementName.isCustom()) {
             popName = checkPopName(popName);
         }
         // ]NOCPP]
-        T elt = createElement("http://www.w3.org/2000/svg", popName, attributes);
+        T elt;
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
-            insertIntoFosterParent(elt);
+            elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes);
         } else {
+            elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node);
             appendElement(elt, current.node);
         }
         elementPushed("http://www.w3.org/2000/svg", popName, elt);
         elementPopped("http://www.w3.org/2000/svg", popName, elt);
     }
 
     private void appendVoidElementToCurrentMayFosterMathML(
             ElementName elementName, HtmlAttributes attributes)
             throws SAXException {
         @Local String popName = elementName.name;
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML");
         if (elementName.isCustom()) {
             popName = checkPopName(popName);
         }
         // ]NOCPP]
-        T elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes);
+        T elt;
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
-            insertIntoFosterParent(elt);
+            elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes);
         } else {
+            elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node);
             appendElement(elt, current.node);
         }
         elementPushed("http://www.w3.org/1998/Math/MathML", popName, elt);
         elementPopped("http://www.w3.org/1998/Math/MathML", popName, elt);
     }
 
     private void appendVoidElementToCurrent(
             @Local String name, HtmlAttributes attributes, T form) throws SAXException {
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         // ]NOCPP]
         // Can't be called for custom elements
+        T currentNode = stack[currentPtr].node;
         T elt = createElement("http://www.w3.org/1999/xhtml", name, attributes,
-                form == null || fragment || isTemplateContents() ? null : form);
-        StackNode<T> current = stack[currentPtr];
-        appendElement(elt, current.node);
+                form == null || fragment || isTemplateContents() ? null : form, currentNode);
+        appendElement(elt, currentNode);
         elementPushed("http://www.w3.org/1999/xhtml", name, elt);
         elementPopped("http://www.w3.org/1999/xhtml", name, elt);
     }
 
     private void appendVoidFormToCurrent(HtmlAttributes attributes) throws SAXException {
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         // ]NOCPP]
+        T currentNode = stack[currentPtr].node;
         T elt = createElement("http://www.w3.org/1999/xhtml", "form",
-                attributes);
+                attributes, currentNode);
         formPointer = elt;
         // ownership transferred to form pointer
-        StackNode<T> current = stack[currentPtr];
-        appendElement(elt, current.node);
+        appendElement(elt, currentNode);
         elementPushed("http://www.w3.org/1999/xhtml", "form", elt);
         elementPopped("http://www.w3.org/1999/xhtml", "form", elt);
     }
 
     // [NOCPP[
 
     private final void accumulateCharactersForced(@Const @NoLength char[] buf,
             int start, int length) throws SAXException {
@@ -5573,21 +5613,21 @@ public abstract class TreeBuilder<T> imp
 
     // ------------------------------- //
 
     protected final void requestSuspension() {
         tokenizer.requestSuspension();
     }
 
     protected abstract T createElement(@NsUri String ns, @Local String name,
-            HtmlAttributes attributes) throws SAXException;
+            HtmlAttributes attributes, T intendedParent) throws SAXException;
 
     protected T createElement(@NsUri String ns, @Local String name,
-            HtmlAttributes attributes, T form) throws SAXException {
-        return createElement("http://www.w3.org/1999/xhtml", name, attributes);
+            HtmlAttributes attributes, T form, T intendedParent) throws SAXException {
+        return createElement("http://www.w3.org/1999/xhtml", name, attributes, intendedParent);
     }
 
     protected abstract T createHtmlElementSetAsRoot(HtmlAttributes attributes)
             throws SAXException;
 
     protected abstract void detachFromParent(T element) throws SAXException;
 
     protected abstract boolean hasChildren(T element) throws SAXException;
@@ -5596,16 +5636,30 @@ public abstract class TreeBuilder<T> imp
             throws SAXException;
 
     protected abstract void appendChildrenToNewParent(T oldParent, T newParent)
             throws SAXException;
 
     protected abstract void insertFosterParentedChild(T child, T table,
             T stackParent) throws SAXException;
 
+    // We don't generate CPP code for this method because it is not used in generated CPP
+    // code. Instead, the form owner version of this method is called with a null form owner.
+    // [NOCPP[
+
+    protected abstract T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
+            HtmlAttributes attributes, T table, T stackParent) throws SAXException;
+
+    // ]NOCPP]
+
+    protected T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
+            HtmlAttributes attributes, T form, T table, T stackParent) throws SAXException {
+        return createAndInsertFosterParentedElement(ns, name, attributes, table, stackParent);
+    };
+
     protected abstract void insertFosterParentedCharacters(
             @NoLength char[] buf, int start, int length, T table, T stackParent)
             throws SAXException;
 
     protected abstract void appendCharacters(T parent, @NoLength char[] buf,
             int start, int length) throws SAXException;
 
     protected abstract void appendIsindexPrompt(T parent) throws SAXException;
--- a/parser/html/nsHtml5Highlighter.cpp
+++ b/parser/html/nsHtml5Highlighter.cpp
@@ -74,17 +74,17 @@ nsHtml5Highlighter::~nsHtml5Highlighter(
 void
 nsHtml5Highlighter::Start(const nsAutoString& aTitle)
 {
   // Doctype
   mOpQueue.AppendElement()->Init(nsGkAtoms::html, EmptyString(), EmptyString());
 
   mOpQueue.AppendElement()->Init(STANDARDS_MODE);
 
-  nsIContent** root = CreateElement(nsHtml5Atoms::html, nullptr);
+  nsIContent** root = CreateElement(nsHtml5Atoms::html, nullptr, nullptr);
   mOpQueue.AppendElement()->Init(eTreeOpAppendToDocument, root);
   mStack.AppendElement(root);
 
   Push(nsGkAtoms::head, nullptr);
 
   Push(nsGkAtoms::title, nullptr);
   // XUL will add the "Source of: " prefix.
   uint32_t length = aTitle.Length();
@@ -650,41 +650,43 @@ nsHtml5Highlighter::AllocateContentHandl
 #ifdef DEBUG
   mHandles[mHandlesUsed] = (nsIContent*)0xC0DEDBAD;
 #endif
   return &mHandles[mHandlesUsed++];
 }
 
 nsIContent**
 nsHtml5Highlighter::CreateElement(nsIAtom* aName,
-                                  nsHtml5HtmlAttributes* aAttributes)
+                                  nsHtml5HtmlAttributes* aAttributes,
+                                  nsIContent** aIntendedParent)
 {
   NS_PRECONDITION(aName, "Got null name.");
   nsIContent** content = AllocateContentHandle();
   mOpQueue.AppendElement()->Init(kNameSpaceID_XHTML,
                                  aName,
                                  aAttributes,
                                  content,
+                                 aIntendedParent,
                                  true);
   return content;
 }
 
 nsIContent**
 nsHtml5Highlighter::CurrentNode()
 {
   NS_PRECONDITION(mStack.Length() >= 1, "Must have something on stack.");
   return mStack[mStack.Length() - 1];
 }
 
 void
 nsHtml5Highlighter::Push(nsIAtom* aName,
                          nsHtml5HtmlAttributes* aAttributes)
 {
   NS_PRECONDITION(mStack.Length() >= 1, "Pushing without root.");
-  nsIContent** elt = CreateElement(aName, aAttributes); // Don't inline below!
+  nsIContent** elt = CreateElement(aName, aAttributes, CurrentNode()); // Don't inline below!
   mOpQueue.AppendElement()->Init(eTreeOpAppend, elt, CurrentNode());
   mStack.AppendElement(elt);
 }
 
 void
 nsHtml5Highlighter::Pop()
 {
   NS_PRECONDITION(mStack.Length() >= 2, "Popping when stack too short.");
--- a/parser/html/nsHtml5Highlighter.h
+++ b/parser/html/nsHtml5Highlighter.h
@@ -221,20 +221,22 @@ class nsHtml5Highlighter
     nsIContent** AllocateContentHandle();
 
     /**
      * Enqueues an element creation tree operation.
      *
      * @param aName the name of the element
      * @param aAttributes the attribute holder (ownership will be taken) or
      *        nullptr for no attributes
+     * @param aIntendedParent the intended parent node for the created element
      * @return the handle for the element that will be created
      */
     nsIContent** CreateElement(nsIAtom* aName,
-                               nsHtml5HtmlAttributes* aAttributes);
+                               nsHtml5HtmlAttributes* aAttributes,
+                               nsIContent** aIntendedParent);
 
     /**
      * Gets the handle for the current node. May be called only after the
      * root element has been set.
      *
      * @return the handle for the current node
      */
     nsIContent** CurrentNode();
--- a/parser/html/nsHtml5TreeBuilder.cpp
+++ b/parser/html/nsHtml5TreeBuilder.cpp
@@ -140,17 +140,17 @@ nsHtml5TreeBuilder::startTokenization(ns
         tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_DATA, contextName);
       }
     }
     contextName = nullptr;
     contextNode = nullptr;
   } else {
     mode = NS_HTML5TREE_BUILDER_INITIAL;
     if (tokenizer->isViewingXmlSource()) {
-      nsIContentHandle* elt = createElement(kNameSpaceID_SVG, nsHtml5Atoms::svg, tokenizer->emptyAttributes());
+      nsIContentHandle* elt = createElement(kNameSpaceID_SVG, nsHtml5Atoms::svg, tokenizer->emptyAttributes(), nullptr);
       nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_SVG, nsHtml5Atoms::svg, elt);
       currentPtr++;
       stack[currentPtr] = node;
     }
   }
 }
 
 void 
@@ -3641,17 +3641,17 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag
         furthestBlockPos--;
         continue;
       }
       if (nodePos == furthestBlockPos) {
         bookmark = nodeListPos + 1;
       }
       MOZ_ASSERT(node == listOfActiveFormattingElements[nodeListPos]);
       MOZ_ASSERT(node == stack[nodePos]);
-      nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes(nullptr));
+      nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes(nullptr), commonAncestor->node);
       nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, node->name, clone, node->popName, node->attributes);
       node->dropAttributes();
       stack[nodePos] = newNode;
       newNode->retain();
       listOfActiveFormattingElements[nodeListPos] = newNode;
       node->release();
       node->release();
       node = newNode;
@@ -3662,17 +3662,17 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag
     if (commonAncestor->isFosterParenting()) {
 
       detachFromParent(lastNode->node);
       insertIntoFosterParent(lastNode->node);
     } else {
       detachFromParent(lastNode->node);
       appendElement(lastNode->node, commonAncestor->node);
     }
-    nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, formattingElt->name, formattingElt->attributes->cloneAttributes(nullptr));
+    nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, formattingElt->name, formattingElt->attributes->cloneAttributes(nullptr), furthestBlock->node);
     nsHtml5StackNode* formattingClone = new nsHtml5StackNode(formattingElt->getFlags(), formattingElt->ns, formattingElt->name, clone, formattingElt->popName, formattingElt->attributes);
     formattingElt->dropAttributes();
     appendChildrenToNewParent(furthestBlock->node, clone);
     appendElement(clone, furthestBlock->node);
     removeFromListOfActiveFormattingElements(formattingEltListPos);
     insertIntoListOfActiveFormattingElements(formattingClone, bookmark);
     MOZ_ASSERT(formattingEltStackPos < furthestBlockPos);
     removeFromStack(formattingEltStackPos);
@@ -3823,25 +3823,26 @@ nsHtml5TreeBuilder::reconstructTheActive
     }
     if (isInStack(listOfActiveFormattingElements[entryPos])) {
       break;
     }
   }
   while (entryPos < listPtr) {
     entryPos++;
     nsHtml5StackNode* entry = listOfActiveFormattingElements[entryPos];
-    nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr));
+    nsHtml5StackNode* currentNode = stack[currentPtr];
+    nsIContentHandle* clone;
+    if (currentNode->isFosterParenting()) {
+      clone = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr));
+    } else {
+      clone = createElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr), currentNode->node);
+      appendElement(clone, currentNode->node);
+    }
     nsHtml5StackNode* entryClone = new nsHtml5StackNode(entry->getFlags(), entry->ns, entry->name, clone, entry->popName, entry->attributes);
     entry->dropAttributes();
-    nsHtml5StackNode* currentNode = stack[currentPtr];
-    if (currentNode->isFosterParenting()) {
-      insertIntoFosterParent(clone);
-    } else {
-      appendElement(clone, currentNode->node);
-    }
     push(entryClone);
     listOfActiveFormattingElements[entryPos] = entryClone;
     entry->release();
     entryClone->retain();
   }
 }
 
 void 
@@ -3852,16 +3853,36 @@ nsHtml5TreeBuilder::insertIntoFosterPare
   if (templatePos >= tablePos) {
     appendElement(child, stack[templatePos]->node);
     return;
   }
   nsHtml5StackNode* node = stack[tablePos];
   insertFosterParentedChild(child, node->node, stack[tablePos - 1]->node);
 }
 
+nsIContentHandle* 
+nsHtml5TreeBuilder::createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes)
+{
+  return createAndInsertFosterParentedElement(ns, name, attributes, nullptr);
+}
+
+nsIContentHandle* 
+nsHtml5TreeBuilder::createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
+{
+  int32_t tablePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE);
+  int32_t templatePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TEMPLATE);
+  if (templatePos >= tablePos) {
+    nsIContentHandle* child = createElement(ns, name, attributes, form, stack[templatePos]->node);
+    appendElement(child, stack[templatePos]->node);
+    return child;
+  }
+  nsHtml5StackNode* node = stack[tablePos];
+  return createAndInsertFosterParentedElement(ns, name, attributes, form, node->node, stack[tablePos - 1]->node);
+}
+
 bool 
 nsHtml5TreeBuilder::isInStack(nsHtml5StackNode* node)
 {
   for (int32_t i = currentPtr; i >= 0; i--) {
     if (stack[i] == node) {
       return true;
     }
   }
@@ -3916,18 +3937,19 @@ void
 nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush()
 {
   appendHtmlElementToDocumentAndPush(tokenizer->emptyAttributes());
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::head, attributes);
-  appendElement(elt, stack[currentPtr]->node);
+  nsIContentHandle* currentNode = stack[currentPtr]->node;
+  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::head, attributes, currentNode);
+  appendElement(elt, currentNode);
   headPointer = elt;
   nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HEAD, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(nsHtml5HtmlAttributes* attributes)
 {
@@ -3938,91 +3960,96 @@ void
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement()
 {
   appendToCurrentNodeAndPushBodyElement(tokenizer->emptyAttributes());
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(nsHtml5HtmlAttributes* attributes)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes);
-  if (!isTemplateContents()) {
-    formPointer = elt;
-  }
+  nsIContentHandle* elt;
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
-    insertIntoFosterParent(elt);
+    elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes);
   } else {
+    elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes, current->node);
     appendElement(elt, current->node);
   }
+  if (!isTemplateContents()) {
+    formPointer = elt;
+  }
   nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_FORM, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   nsHtml5HtmlAttributes* clone = attributes->cloneAttributes(nullptr);
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes);
+  nsIContentHandle* elt;
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
-    insertIntoFosterParent(elt);
+    elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->name, attributes);
   } else {
+    elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, current->node);
     appendElement(elt, current->node);
   }
   nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, clone);
   push(node);
   append(node);
   node->retain();
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes);
-  appendElement(elt, stack[currentPtr]->node);
+  nsIContentHandle* currentNode = stack[currentPtr]->node;
+  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, currentNode);
+  appendElement(elt, currentNode);
   if (nsHtml5ElementName::ELT_TEMPLATE == elementName) {
     elt = getDocumentFragmentForTemplate(elt);
   }
   nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   nsIAtom* popName = elementName->name;
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, popName, attributes);
+  nsIContentHandle* elt;
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
-    insertIntoFosterParent(elt);
+    elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, popName, attributes);
   } else {
+    elt = createElement(kNameSpaceID_XHTML, popName, attributes, current->node);
     appendElement(elt, current->node);
   }
   nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   nsIAtom* popName = elementName->name;
   bool markAsHtmlIntegrationPoint = false;
   if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName && annotationXmlEncodingPermitsHtml(attributes)) {
     markAsHtmlIntegrationPoint = true;
   }
-  nsIContentHandle* elt = createElement(kNameSpaceID_MathML, popName, attributes);
+  nsIContentHandle* elt;
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
-    insertIntoFosterParent(elt);
+    elt = createAndInsertFosterParentedElement(kNameSpaceID_MathML, popName, attributes);
   } else {
+    elt = createElement(kNameSpaceID_MathML, popName, attributes, current->node);
     appendElement(elt, current->node);
   }
   nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
   push(node);
 }
 
 bool 
 nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(nsHtml5HtmlAttributes* attributes)
@@ -4033,134 +4060,142 @@ nsHtml5TreeBuilder::annotationXmlEncodin
   }
   return nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("application/xhtml+xml", encoding) || nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("text/html", encoding);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   nsIAtom* popName = elementName->camelCaseName;
-  nsIContentHandle* elt = createElement(kNameSpaceID_SVG, popName, attributes);
+  nsIContentHandle* elt;
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
-    insertIntoFosterParent(elt);
+    elt = createAndInsertFosterParentedElement(kNameSpaceID_SVG, popName, attributes);
   } else {
+    elt = createElement(kNameSpaceID_SVG, popName, attributes, current->node);
     appendElement(elt, current->node);
   }
   nsHtml5StackNode* node = new nsHtml5StackNode(elementName, popName, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, !form || fragment || isTemplateContents() ? nullptr : form);
+  nsIContentHandle* elt;
+  nsIContentHandle* formOwner = !form || fragment || isTemplateContents() ? nullptr : form;
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
-    insertIntoFosterParent(elt);
+    elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->name, attributes, formOwner);
   } else {
+    elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, formOwner, current->node);
     appendElement(elt, current->node);
   }
   nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form);
+  nsIContentHandle* elt;
+  nsIContentHandle* formOwner = !form || fragment || isTemplateContents() ? nullptr : form;
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
-    insertIntoFosterParent(elt);
+    elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, name, attributes, formOwner);
   } else {
+    elt = createElement(kNameSpaceID_XHTML, name, attributes, formOwner, current->node);
     appendElement(elt, current->node);
   }
   elementPushed(kNameSpaceID_XHTML, name, elt);
   elementPopped(kNameSpaceID_XHTML, name, elt);
 }
 
 void 
 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   nsIAtom* popName = elementName->name;
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, popName, attributes);
+  nsIContentHandle* elt;
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
-    insertIntoFosterParent(elt);
+    elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, popName, attributes);
   } else {
+    elt = createElement(kNameSpaceID_XHTML, popName, attributes, current->node);
     appendElement(elt, current->node);
   }
   elementPushed(kNameSpaceID_XHTML, popName, elt);
   elementPopped(kNameSpaceID_XHTML, popName, elt);
 }
 
 void 
 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   nsIAtom* popName = elementName->camelCaseName;
-  nsIContentHandle* elt = createElement(kNameSpaceID_SVG, popName, attributes);
+  nsIContentHandle* elt;
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
-    insertIntoFosterParent(elt);
+    elt = createAndInsertFosterParentedElement(kNameSpaceID_SVG, popName, attributes);
   } else {
+    elt = createElement(kNameSpaceID_SVG, popName, attributes, current->node);
     appendElement(elt, current->node);
   }
   elementPushed(kNameSpaceID_SVG, popName, elt);
   elementPopped(kNameSpaceID_SVG, popName, elt);
 }
 
 void 
 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   nsIAtom* popName = elementName->name;
-  nsIContentHandle* elt = createElement(kNameSpaceID_MathML, popName, attributes);
+  nsIContentHandle* elt;
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
-    insertIntoFosterParent(elt);
+    elt = createAndInsertFosterParentedElement(kNameSpaceID_MathML, popName, attributes);
   } else {
+    elt = createElement(kNameSpaceID_MathML, popName, attributes, current->node);
     appendElement(elt, current->node);
   }
   elementPushed(kNameSpaceID_MathML, popName, elt);
   elementPopped(kNameSpaceID_MathML, popName, elt);
 }
 
 void 
 nsHtml5TreeBuilder::appendVoidElementToCurrent(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form);
-  nsHtml5StackNode* current = stack[currentPtr];
-  appendElement(elt, current->node);
+  nsIContentHandle* currentNode = stack[currentPtr]->node;
+  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form, currentNode);
+  appendElement(elt, currentNode);
   elementPushed(kNameSpaceID_XHTML, name, elt);
   elementPopped(kNameSpaceID_XHTML, name, elt);
 }
 
 void 
 nsHtml5TreeBuilder::appendVoidFormToCurrent(nsHtml5HtmlAttributes* attributes)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes);
+  nsIContentHandle* currentNode = stack[currentPtr]->node;
+  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes, currentNode);
   formPointer = elt;
-  nsHtml5StackNode* current = stack[currentPtr];
-  appendElement(elt, current->node);
+  appendElement(elt, currentNode);
   elementPushed(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
   elementPopped(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
 }
 
 void 
 nsHtml5TreeBuilder::requestSuspension()
 {
   tokenizer->requestSuspension();
 }
 
-bool 
+;bool 
 nsHtml5TreeBuilder::isInForeign()
 {
   return currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML;
 }
 
 bool 
 nsHtml5TreeBuilder::isInForeignButNotHtmlOrMathTextIntegrationPoint()
 {
--- a/parser/html/nsHtml5TreeBuilder.h
+++ b/parser/html/nsHtml5TreeBuilder.h
@@ -172,16 +172,18 @@ class nsHtml5TreeBuilder : public nsAHtm
     void maybeForgetEarlierDuplicateFormattingElement(nsIAtom* name, nsHtml5HtmlAttributes* attributes);
     int32_t findLastOrRoot(nsIAtom* name);
     int32_t findLastOrRoot(int32_t group);
     bool addAttributesToBody(nsHtml5HtmlAttributes* attributes);
     void addAttributesToHtml(nsHtml5HtmlAttributes* attributes);
     void pushHeadPointerOntoStack();
     void reconstructTheActiveFormattingElements();
     void insertIntoFosterParent(nsIContentHandle* child);
+    nsIContentHandle* createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes);
+    nsIContentHandle* createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form);
     bool isInStack(nsHtml5StackNode* node);
     void popTemplateMode();
     void pop();
     void silentPop();
     void popOnEof();
     void appendHtmlElementToDocumentAndPush(nsHtml5HtmlAttributes* attributes);
     void appendHtmlElementToDocumentAndPush();
     void appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes);
@@ -199,25 +201,26 @@ class nsHtml5TreeBuilder : public nsAHtm
     void appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
     void appendVoidElementToCurrentMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
     void appendVoidElementToCurrentMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
     void appendVoidElementToCurrent(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form);
     void appendVoidFormToCurrent(nsHtml5HtmlAttributes* attributes);
   protected:
     void accumulateCharacters(const char16_t* buf, int32_t start, int32_t length);
     void requestSuspension();
-    nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes);
-    nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form);
+    nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* intendedParent);
+    nsIContentHandle* createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form, nsIContentHandle* intendedParent);
     nsIContentHandle* createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* attributes);
     void detachFromParent(nsIContentHandle* element);
     bool hasChildren(nsIContentHandle* element);
     void appendElement(nsIContentHandle* child, nsIContentHandle* newParent);
     void appendChildrenToNewParent(nsIContentHandle* oldParent, nsIContentHandle* newParent);
     void insertFosterParentedChild(nsIContentHandle* child, nsIContentHandle* table, nsIContentHandle* stackParent);
-    void insertFosterParentedCharacters(char16_t* buf, int32_t start, int32_t length, nsIContentHandle* table, nsIContentHandle* stackParent);
+    nsIContentHandle* createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form, nsIContentHandle* table, nsIContentHandle* stackParent);
+    ;void insertFosterParentedCharacters(char16_t* buf, int32_t start, int32_t length, nsIContentHandle* table, nsIContentHandle* stackParent);
     void appendCharacters(nsIContentHandle* parent, char16_t* buf, int32_t start, int32_t length);
     void appendIsindexPrompt(nsIContentHandle* parent);
     void appendComment(nsIContentHandle* parent, char16_t* buf, int32_t start, int32_t length);
     void appendCommentToDocument(char16_t* buf, int32_t start, int32_t length);
     void addAttributesToElement(nsIContentHandle* element, nsHtml5HtmlAttributes* attributes);
     void markMalformedIfScript(nsIContentHandle* elt);
     void start(bool fragmentMode);
     void end();
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -62,47 +62,61 @@ nsHtml5TreeBuilder::nsHtml5TreeBuilder(n
 nsHtml5TreeBuilder::~nsHtml5TreeBuilder()
 {
   MOZ_COUNT_DTOR(nsHtml5TreeBuilder);
   NS_ASSERTION(!mActive, "nsHtml5TreeBuilder deleted without ever calling end() on it!");
   mOpQueue.Clear();
 }
 
 nsIContentHandle*
-nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes)
+nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
+                                  nsHtml5HtmlAttributes* aAttributes,
+                                  nsIContentHandle* aIntendedParent)
 {
   NS_PRECONDITION(aAttributes, "Got null attributes.");
   NS_PRECONDITION(aName, "Got null name.");
   NS_PRECONDITION(aNamespace == kNameSpaceID_XHTML || 
                   aNamespace == kNameSpaceID_SVG || 
                   aNamespace == kNameSpaceID_MathML,
                   "Bogus namespace.");
 
   if (mBuilder) {
     nsCOMPtr<nsIAtom> name = nsHtml5TreeOperation::Reget(aName);
+
+    nsIContent* intendedParent = aIntendedParent ?
+      static_cast<nsIContent*>(aIntendedParent) : nullptr;
+
+    // intendedParent == nullptr is a special case where the
+    // intended parent is the document.
+    nsNodeInfoManager* nodeInfoManager = intendedParent ?
+       intendedParent->OwnerDoc()->NodeInfoManager() :
+       mBuilder->GetNodeInfoManager();
+
     nsIContent* elem =
       nsHtml5TreeOperation::CreateElement(aNamespace,
                                           name,
                                           aAttributes,
                                           mozilla::dom::FROM_PARSER_FRAGMENT,
+                                          nodeInfoManager,
                                           mBuilder);
     if (MOZ_UNLIKELY(aAttributes != tokenizer->GetAttributes() &&
                      aAttributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES)) {
       delete aAttributes;
     }
     return elem;
   }
 
   nsIContentHandle* content = AllocateContentHandle();
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(aNamespace,
                aName,
                aAttributes,
                content,
+               aIntendedParent,
                !!mSpeculativeLoadStage);
   // mSpeculativeLoadStage is non-null only in the off-the-main-thread
   // tree builder, which handles the network stream
   
   // Start wall of code for speculative loading and line numbers
   
   if (mSpeculativeLoadStage) {
     switch (aNamespace) {
@@ -252,50 +266,100 @@ nsHtml5TreeBuilder::createElement(int32_
   }
 
   // End wall of code for speculative loading
   
   return content;
 }
 
 nsIContentHandle*
-nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes, nsIContentHandle* aFormElement)
+nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
+                                  nsHtml5HtmlAttributes* aAttributes,
+                                  nsIContentHandle* aFormElement,
+                                  nsIContentHandle* aIntendedParent)
 {
-  nsIContentHandle* content = createElement(aNamespace, aName, aAttributes);
+  nsIContentHandle* content = createElement(aNamespace, aName, aAttributes,
+                                            aIntendedParent);
   if (aFormElement) {
     if (mBuilder) {
       nsHtml5TreeOperation::SetFormElement(static_cast<nsIContent*>(content),
         static_cast<nsIContent*>(aFormElement));
     } else {
       nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
       NS_ASSERTION(treeOp, "Tree op allocation failed.");
       treeOp->Init(eTreeOpSetFormElement, content, aFormElement);
     }
   }
   return content;
 }
 
 nsIContentHandle*
 nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* aAttributes)
 {
-  nsIContentHandle* content = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::html, aAttributes);
+  nsIContentHandle* content = createElement(kNameSpaceID_XHTML,
+                                            nsHtml5Atoms::html,
+                                            aAttributes,
+                                            nullptr);
   if (mBuilder) {
     nsresult rv = nsHtml5TreeOperation::AppendToDocument(static_cast<nsIContent*>(content),
                                                          mBuilder);
     if (NS_FAILED(rv)) {
       MarkAsBrokenAndRequestSuspension(rv);
     }
   } else {
     nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     NS_ASSERTION(treeOp, "Tree op allocation failed.");
     treeOp->Init(eTreeOpAppendToDocument, content);
   }
   return content;
 }
 
+nsIContentHandle*
+nsHtml5TreeBuilder::createAndInsertFosterParentedElement(int32_t aNamespace, nsIAtom* aName,
+                                                         nsHtml5HtmlAttributes* aAttributes,
+                                                         nsIContentHandle* aFormElement,
+                                                         nsIContentHandle* aTable,
+                                                         nsIContentHandle* aStackParent)
+{
+  NS_PRECONDITION(aTable, "Null table");
+  NS_PRECONDITION(aStackParent, "Null stack parent");
+
+  if (mBuilder) {
+    // Get the foster parent to use as the intended parent when creating
+    // the child element.
+    nsIContent* fosterParent = nsHtml5TreeOperation::GetFosterParent(
+      static_cast<nsIContent*>(aTable),
+      static_cast<nsIContent*>(aStackParent));
+
+    nsIContentHandle* child = createElement(aNamespace, aName, aAttributes,
+      aFormElement, fosterParent);
+
+    insertFosterParentedChild(child, aTable, aStackParent);
+
+    return child;
+  }
+
+  // Tree op to get the foster parent that we use as the intended parent
+  // when creating the child element.
+  nsHtml5TreeOperation* fosterParentTreeOp = mOpQueue.AppendElement();
+  NS_ASSERTION(fosterParentTreeOp, "Tree op allocation failed.");
+  nsIContentHandle* fosterParentHandle = AllocateContentHandle();
+  fosterParentTreeOp->Init(eTreeOpGetFosterParent, aTable,
+                           aStackParent, fosterParentHandle);
+
+  // Create the element with the correct intended parent.
+  nsIContentHandle* child = createElement(aNamespace, aName, aAttributes,
+    aFormElement, fosterParentHandle);
+
+  // Insert the child into the foster parent.
+  insertFosterParentedChild(child, aTable, aStackParent);
+
+  return child;
+}
+
 void
 nsHtml5TreeBuilder::detachFromParent(nsIContentHandle* aElement)
 {
   NS_PRECONDITION(aElement, "Null element");
 
   if (mBuilder) {
     nsHtml5TreeOperation::Detach(static_cast<nsIContent*>(aElement),
                                  mBuilder);
--- a/parser/html/nsHtml5TreeOperation.cpp
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -153,17 +153,18 @@ nsHtml5TreeOperation::AppendText(const c
     nsHtml5OtherDocUpdate update(aParent->OwnerDoc(),
                                  aBuilder->GetDocument());
     return AppendTextToTextNode(aBuffer, 
                                 aLength, 
                                 lastChild, 
                                 aBuilder);
   }
 
-  nsRefPtr<nsTextNode> text = new nsTextNode(aBuilder->GetNodeInfoManager());
+  nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager();
+  nsRefPtr<nsTextNode> text = new nsTextNode(nodeInfoManager);
   NS_ASSERTION(text, "Infallible malloc failed?");
   rv = text->SetText(aBuffer, aLength, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return Append(text, aParent, aBuilder);
 }
 
 nsresult
@@ -330,25 +331,26 @@ nsHtml5TreeOperation::AddAttributes(nsIC
 }
 
 
 nsIContent*
 nsHtml5TreeOperation::CreateElement(int32_t aNs,
                                     nsIAtom* aName,
                                     nsHtml5HtmlAttributes* aAttributes,
                                     mozilla::dom::FromParser aFromParser,
+                                    nsNodeInfoManager* aNodeInfoManager,
                                     nsHtml5DocumentBuilder* aBuilder)
 {
   bool isKeygen = (aName == nsHtml5Atoms::keygen && aNs == kNameSpaceID_XHTML);
   if (MOZ_UNLIKELY(isKeygen)) {
     aName = nsHtml5Atoms::select;
   }
 
   nsCOMPtr<dom::Element> newElement;
-  nsRefPtr<dom::NodeInfo> nodeInfo = aBuilder->GetNodeInfoManager()->
+  nsRefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->
     GetNodeInfo(aName, nullptr, aNs, nsIDOMNode::ELEMENT_NODE);
   NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
   NS_NewElement(getter_AddRefs(newElement),
                 nodeInfo.forget(),
                 aFromParser);
   NS_ASSERTION(newElement, "Element creation created null pointer.");
 
   dom::Element* newContent = newElement;
@@ -378,29 +380,28 @@ nsHtml5TreeOperation::CreateElement(int3
 
     newContent->SetAttr(kNameSpaceID_None,
                         nsGkAtoms::moztype,
                         nullptr,
                         theAttribute,
                         false);
 
     nsRefPtr<dom::NodeInfo> optionNodeInfo =
-      aBuilder->GetNodeInfoManager()->GetNodeInfo(nsHtml5Atoms::option,
-                                                  nullptr,
-                                                  kNameSpaceID_XHTML,
-                                                  nsIDOMNode::ELEMENT_NODE);
+      aNodeInfoManager->GetNodeInfo(nsHtml5Atoms::option,
+                                    nullptr,
+                                    kNameSpaceID_XHTML,
+                                    nsIDOMNode::ELEMENT_NODE);
 
     for (uint32_t i = 0; i < theContent.Length(); ++i) {
       nsCOMPtr<dom::Element> optionElt;
       nsRefPtr<dom::NodeInfo> ni = optionNodeInfo;
       NS_NewElement(getter_AddRefs(optionElt),
                     ni.forget(),
                     aFromParser);
-      nsRefPtr<nsTextNode> optionText =
-        new nsTextNode(aBuilder->GetNodeInfoManager());
+      nsRefPtr<nsTextNode> optionText = new nsTextNode(aNodeInfoManager);
       (void) optionText->SetText(theContent[i], false);
       optionElt->AppendChildTo(optionText, false);
       newContent->AppendChildTo(optionElt, false);
       // XXXsmaug Shouldn't we call this after adding all the child nodes.
       newContent->DoneAddingChildren(false);
     }
   }
 
@@ -512,18 +513,18 @@ nsHtml5TreeOperation::FosterParentText(n
     nsIContent* previousSibling = aTable->GetPreviousSibling();
     if (previousSibling && previousSibling->IsNodeOfType(nsINode::eTEXT)) {
       return AppendTextToTextNode(aBuffer,
                                   aLength,
                                   previousSibling,
                                   aBuilder);
     }
 
-    nsRefPtr<nsTextNode> text =
-      new nsTextNode(aBuilder->GetNodeInfoManager());
+    nsNodeInfoManager* nodeInfoManager = aStackParent->OwnerDoc()->NodeInfoManager();
+    nsRefPtr<nsTextNode> text = new nsTextNode(nodeInfoManager);
     NS_ASSERTION(text, "Infallible malloc failed?");
     rv = text->SetText(aBuffer, aLength, false);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = foster->InsertChildAt(text, pos, false);
     NS_ENSURE_SUCCESS(rv, rv);
     nsNodeUtils::ContentInserted(foster, text, pos);
     return rv;
@@ -533,18 +534,18 @@ nsHtml5TreeOperation::FosterParentText(n
 }
 
 nsresult
 nsHtml5TreeOperation::AppendComment(nsIContent* aParent,
                                     char16_t* aBuffer,
                                     int32_t aLength,
                                     nsHtml5DocumentBuilder* aBuilder)
 {
-  nsRefPtr<dom::Comment> comment =
-    new dom::Comment(aBuilder->GetNodeInfoManager());
+  nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager();
+  nsRefPtr<dom::Comment> comment = new dom::Comment(nodeInfoManager);
   NS_ASSERTION(comment, "Infallible malloc failed?");
   nsresult rv = comment->SetText(aBuffer, aLength, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return Append(comment, aParent, aBuilder);
 }
 
 nsresult
@@ -587,16 +588,23 @@ nsIContent*
 nsHtml5TreeOperation::GetDocumentFragmentForTemplate(nsIContent* aNode)
 {
   dom::HTMLTemplateElement* tempElem =
     static_cast<dom::HTMLTemplateElement*>(aNode);
   nsRefPtr<dom::DocumentFragment> frag = tempElem->Content();
   return frag;
 }
 
+nsIContent*
+nsHtml5TreeOperation::GetFosterParent(nsIContent* aTable, nsIContent* aStackParent)
+{
+  nsIContent* tableParent = aTable->GetParent();
+  return IsElementOrTemplateContent(tableParent) ? tableParent : aStackParent;
+}
+
 void
 nsHtml5TreeOperation::PreventScriptExecution(nsIContent* aNode)
 {
   nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode);
   MOZ_ASSERT(sele);
   sele->PreventExecution();
 }
 
@@ -667,23 +675,31 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
       return AddAttributes(node, attributes, aBuilder);
     }
     case eTreeOpCreateElementNetwork:
     case eTreeOpCreateElementNotNetwork: {
       nsIContent** target = mOne.node;
       int32_t ns = mFour.integer;
       nsCOMPtr<nsIAtom> name = Reget(mTwo.atom);
       nsHtml5HtmlAttributes* attributes = mThree.attributes;
+      nsIContent* intendedParent = mFive.node ? *(mFive.node) : nullptr;
+
+      // intendedParent == nullptr is a special case where the
+      // intended parent is the document.
+      nsNodeInfoManager* nodeInfoManager = intendedParent ?
+         intendedParent->OwnerDoc()->NodeInfoManager() :
+         aBuilder->GetNodeInfoManager();
 
       *target = CreateElement(ns,
                               name,
                               attributes,
                               mOpCode == eTreeOpCreateElementNetwork ?
                                 dom::FROM_PARSER_NETWORK :
                                 dom::FROM_PARSER_DOCUMENT_WRITE,
+                              nodeInfoManager,
                               aBuilder);
       return NS_OK;
     }
     case eTreeOpSetFormElement: {
       nsIContent* node = *(mOne.node);
       nsIContent* parent = *(mTwo.node);
       SetFormElement(node, parent);
       return NS_OK;
@@ -724,16 +740,23 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
       pair->Get(publicId, systemId);
       return AppendDoctypeToDocument(name, publicId, systemId, aBuilder);
     }
     case eTreeOpGetDocumentFragmentForTemplate: {
       nsIContent* node = *(mOne.node);
       *mTwo.node = GetDocumentFragmentForTemplate(node);
       return NS_OK;
     }
+    case eTreeOpGetFosterParent: {
+      nsIContent* table = *(mOne.node);
+      nsIContent* stackParent = *(mTwo.node);
+      nsIContent* fosterParent = GetFosterParent(table, stackParent);
+      *mThree.node = fosterParent;
+      return NS_OK;
+    }
     case eTreeOpMarkAsBroken: {
       return mOne.result;
     }
     case eTreeOpRunScript: {
       nsIContent* node = *(mOne.node);
       nsAHtml5TreeBuilderState* snapshot = mTwo.state;
       if (snapshot) {
         aBuilder->InitializeDocWriteParserState(snapshot, mFour.integer);
--- a/parser/html/nsHtml5TreeOperation.h
+++ b/parser/html/nsHtml5TreeOperation.h
@@ -30,16 +30,17 @@ enum eHtml5TreeOperation {
   eTreeOpSetFormElement,
   eTreeOpAppendText,
   eTreeOpAppendIsindexPrompt,
   eTreeOpFosterParentText,
   eTreeOpAppendComment,
   eTreeOpAppendCommentToDocument,
   eTreeOpAppendDoctypeToDocument,
   eTreeOpGetDocumentFragmentForTemplate,
+  eTreeOpGetFosterParent,
   // Gecko-specific on-pop ops
   eTreeOpMarkAsBroken,
   eTreeOpRunScript,
   eTreeOpRunScriptAsyncDefer,
   eTreeOpPreventScriptExecution,
   eTreeOpDoneAddingChildren,
   eTreeOpDoneCreatingElement,
   eTreeOpSetDocumentCharset,
@@ -144,16 +145,17 @@ class nsHtml5TreeOperation {
     static nsresult AddAttributes(nsIContent* aNode,
                                   nsHtml5HtmlAttributes* aAttributes,
                                   nsHtml5DocumentBuilder* aBuilder);
 
     static nsIContent* CreateElement(int32_t aNs,
                                      nsIAtom* aName,
                                      nsHtml5HtmlAttributes* aAttributes,
                                      mozilla::dom::FromParser aFromParser,
+                                     nsNodeInfoManager* aNodeInfoManager,
                                      nsHtml5DocumentBuilder* aBuilder);
 
     static void SetFormElement(nsIContent* aNode, nsIContent* aParent);
 
     static nsresult AppendIsindexPrompt(nsIContent* parent,
                                         nsHtml5DocumentBuilder* aBuilder);
 
     static nsresult FosterParentText(nsIContent* aStackParent,
@@ -173,16 +175,18 @@ class nsHtml5TreeOperation {
 
     static nsresult AppendDoctypeToDocument(nsIAtom* aName,
                                             const nsAString& aPublicId,
                                             const nsAString& aSystemId,
                                             nsHtml5DocumentBuilder* aBuilder);
 
     static nsIContent* GetDocumentFragmentForTemplate(nsIContent* aNode);
 
+    static nsIContent* GetFosterParent(nsIContent* aTable, nsIContent* aStackParent);
+
     static void PreventScriptExecution(nsIContent* aNode);
 
     static void DoneAddingChildren(nsIContent* aNode);
 
     static void DoneCreatingElement(nsIContent* aNode);
 
     static void SvgLoad(nsIContent* aNode);
 
@@ -283,26 +287,28 @@ class nsHtml5TreeOperation {
       mOne.node = static_cast<nsIContent**>(aNode);
       mTwo.state = nullptr;
     }
     
     inline void Init(int32_t aNamespace, 
                      nsIAtom* aName, 
                      nsHtml5HtmlAttributes* aAttributes,
                      nsIContentHandle* aTarget,
+                     nsIContentHandle* aIntendedParent,
                      bool aFromNetwork)
     {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aName, "Initialized tree op with null name.");
       NS_PRECONDITION(aTarget, "Initialized tree op with null target node.");
       mOpCode = aFromNetwork ?
                 eTreeOpCreateElementNetwork :
                 eTreeOpCreateElementNotNetwork;
       mFour.integer = aNamespace;
+      mFive.node = static_cast<nsIContent**>(aIntendedParent);
       mOne.node = static_cast<nsIContent**>(aTarget);
       mTwo.atom = aName;
       if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
         mThree.attributes = nullptr;
       } else {
         mThree.attributes = aAttributes;
       }
     }
@@ -494,12 +500,12 @@ class nsHtml5TreeOperation {
       nsHtml5HtmlAttributes*          attributes;
       nsHtml5DocumentMode             mode;
       char16_t*                       unicharPtr;
       char*                           charPtr;
       nsHtml5TreeOperationStringPair* stringPair;
       nsAHtml5TreeBuilderState*       state;
       int32_t                         integer;
       nsresult                        result;
-    }                   mOne, mTwo, mThree, mFour;
+    } mOne, mTwo, mThree, mFour, mFive;
 };
 
 #endif // nsHtml5TreeOperation_h