Backed out 8 changesets (bug 959150) for Linux debug build bustage on a CLOSED TREE.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 05 Mar 2014 15:26:07 -0500
changeset 172117 e420695e207978ed4e90eb0cead0678220b94d4e
parent 172116 5cc5d321b2b61016df50ebdcef95b8c44e79814b
child 172118 ab9d624f94616190b07570198b8071e7405479f4
push id26349
push userkwierso@gmail.com
push dateThu, 06 Mar 2014 02:08:58 +0000
treeherdermozilla-central@c7d401d189e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs959150
milestone30.0a1
backs out30bdc9b15e8e0677f23fb68a159bf3c38421c04e
630e489aed3049dcebb2cd2b997b88f4a9d03743
c6874004efe7920f1d5bda0a925428750df5d016
ebc67518a962c890acc5e1a8810a90ea8543a64d
14441e5285826c348ac560bad0d240b2f64f14a4
8d0ae8bffb08bc71bde1b7639f3b3b8959051def
603b63c33e9a380a02dec528ce35264e50c3fd2a
261e2d244c547a157286b06c08bf3352432f2e5d
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 8 changesets (bug 959150) for Linux debug build bustage on a CLOSED TREE. Backed out changeset 30bdc9b15e8e (bug 959150) Backed out changeset 630e489aed30 (bug 959150) Backed out changeset c6874004efe7 (bug 959150) Backed out changeset ebc67518a962 (bug 959150) Backed out changeset 14441e528582 (bug 959150) Backed out changeset 8d0ae8bffb08 (bug 959150) Backed out changeset 603b63c33e9a (bug 959150) Backed out changeset 261e2d244c54 (bug 959150)
parser/html/javasrc/Tokenizer.java
parser/html/javasrc/TreeBuilder.java
parser/html/moz.build
parser/html/nsAHtml5TreeBuilderState.h
parser/html/nsHtml5AtomTable.h
parser/html/nsHtml5AttributeName.cpp
parser/html/nsHtml5AttributeName.h
parser/html/nsHtml5DocumentBuilder.cpp
parser/html/nsHtml5DocumentBuilder.h
parser/html/nsHtml5ElementName.cpp
parser/html/nsHtml5ElementName.h
parser/html/nsHtml5HtmlAttributes.cpp
parser/html/nsHtml5HtmlAttributes.h
parser/html/nsHtml5MetaScanner.cpp
parser/html/nsHtml5MetaScanner.h
parser/html/nsHtml5MetaScannerHSupplement.h
parser/html/nsHtml5OplessBuilder.cpp
parser/html/nsHtml5OplessBuilder.h
parser/html/nsHtml5Parser.h
parser/html/nsHtml5PendingNotification.h
parser/html/nsHtml5Portability.h
parser/html/nsHtml5Speculation.h
parser/html/nsHtml5SpeculativeLoad.h
parser/html/nsHtml5StackNode.cpp
parser/html/nsHtml5StackNode.h
parser/html/nsHtml5StateSnapshot.cpp
parser/html/nsHtml5StateSnapshot.h
parser/html/nsHtml5StreamParser.h
parser/html/nsHtml5StringParser.cpp
parser/html/nsHtml5StringParser.h
parser/html/nsHtml5Tokenizer.cpp
parser/html/nsHtml5Tokenizer.h
parser/html/nsHtml5TokenizerHSupplement.h
parser/html/nsHtml5TokenizerLoopPolicies.h
parser/html/nsHtml5TreeBuilder.cpp
parser/html/nsHtml5TreeBuilder.h
parser/html/nsHtml5TreeBuilderCppSupplement.h
parser/html/nsHtml5TreeBuilderHSupplement.h
parser/html/nsHtml5TreeOpExecutor.cpp
parser/html/nsHtml5TreeOpExecutor.h
parser/html/nsHtml5TreeOperation.cpp
parser/html/nsHtml5TreeOperation.h
parser/html/nsHtml5UTF16Buffer.cpp
parser/html/nsHtml5UTF16Buffer.h
parser/html/nsIContentHandle.h
--- a/parser/html/javasrc/Tokenizer.java
+++ b/parser/html/javasrc/Tokenizer.java
@@ -492,22 +492,22 @@ public class Tokenizer implements Locato
     private XmlViolationPolicy commentPolicy = XmlViolationPolicy.ALTER_INFOSET;
 
     private XmlViolationPolicy xmlnsPolicy = XmlViolationPolicy.ALTER_INFOSET;
 
     private XmlViolationPolicy namePolicy = XmlViolationPolicy.ALTER_INFOSET;
 
     private boolean html4ModeCompatibleWithXhtml1Schemata;
 
+    private final boolean newAttributesEachTime;
+
     private int mappingLangToXmlLang;
 
     // ]NOCPP]
 
-    private final boolean newAttributesEachTime;
-
     private boolean shouldSuspend;
 
     protected boolean confident;
 
     private int line;
 
     private Interner interner;
 
@@ -549,22 +549,18 @@ public class Tokenizer implements Locato
         // ]NOCPP]
         this.bmpChar = new char[1];
         this.astralChar = new char[2];
         this.tagName = null;
         this.attributeName = null;
         this.doctypeName = null;
         this.publicIdentifier = null;
         this.systemIdentifier = null;
-        // [NOCPP[
         this.attributes = null;
-        // ]NOCPP]
-        // CPPONLY: this.attributes = tokenHandler.HasBuilder() ? new HtmlAttributes(mappingLangToXmlLang) : null;
-        // CPPONLY: this.newAttributesEachTime = !tokenHandler.HasBuilder();
-        // CPPONLY: this.viewingXmlSource = viewingXmlSource;
+    // CPPONLY: this.viewingXmlSource = viewingXmlSource;
     }
 
     public void setInterner(Interner interner) {
         this.interner = interner;
     }
 
     public void initLocation(String newPublicId, String newSystemId) {
         this.systemId = newSystemId;
@@ -1095,16 +1091,31 @@ public class Tokenizer implements Locato
     public void warn(String message) throws SAXException {
         if (errorHandler == null) {
             return;
         }
         SAXParseException spe = new SAXParseException(message, this);
         errorHandler.warning(spe);
     }
 
+    /**
+     * 
+     */
+    private void resetAttributes() {
+        // [NOCPP[
+        if (newAttributesEachTime) {
+            // ]NOCPP]
+            attributes = null;
+            // [NOCPP[
+        } else {
+            attributes.clear(mappingLangToXmlLang);
+        }
+        // ]NOCPP]
+    }
+
     private void strBufToElementNameString() {
         // if (strBufOffset != -1) {
         // return ElementName.elementNameByBuffer(buf, strBufOffset, strBufLen);
         // } else {
         tagName = ElementName.elementNameByBuffer(strBuf, 0, strBufLen,
                 interner);
         // }
     }
@@ -1120,36 +1131,27 @@ public class Tokenizer implements Locato
             /*
              * When an end tag token is emitted, the content model flag must be
              * switched to the PCDATA state.
              */
             maybeErrAttributesOnEndTag(attrs);
             // CPPONLY: if (!viewingXmlSource) {
             tokenHandler.endTag(tagName);
             // CPPONLY: }
-            // CPPONLY: if (newAttributesEachTime) {
-            // CPPONLY:   Portability.delete(attributes);
-            // CPPONLY:   attributes = null;
-            // CPPONLY: }
+            Portability.delete(attributes);
         } else {
             // CPPONLY: if (viewingXmlSource) {
-            // CPPONLY:   assert newAttributesEachTime;
-            // CPPONLY:   Portability.delete(attributes);
-            // CPPONLY:   attributes = null;
+            // CPPONLY: Portability.delete(attributes);
             // CPPONLY: } else {
             tokenHandler.startTag(tagName, attrs, selfClosing);
             // CPPONLY: }
         }
         tagName.release();
         tagName = null;
-        if (newAttributesEachTime) {
-            attributes = null;
-        } else {
-            attributes.clear(mappingLangToXmlLang);
-        }
+        resetAttributes();
         /*
          * The token handler may have called setStateAndEndTagExpectation
          * and changed stateSave since the start of this method.
          */
         return stateSave;
     }
 
     private void attributeNameComplete() throws SAXException {
@@ -6590,21 +6592,21 @@ public class Tokenizer implements Locato
             tagName.release();
             tagName = null;
         }
         if (attributeName != null) {
             attributeName.release();
             attributeName = null;
         }
         tokenHandler.endTokenization();
-        // [NOCPP[
         if (attributes != null) {
+            attributes.clear(mappingLangToXmlLang);
+            Portability.delete(attributes);
             attributes = null;
         }
-        // ]NOCPP]
     }
 
     public void requestSuspension() {
         shouldSuspend = true;
     }
 
     // [NOCPP[
     
@@ -6673,22 +6675,26 @@ public class Tokenizer implements Locato
         if (tagName != null) {
             tagName.release();
             tagName = null;
         }
         if (attributeName != null) {
             attributeName.release();
             attributeName = null;
         }
+        // [NOCPP[
         if (newAttributesEachTime) {
+            // ]NOCPP]
             if (attributes != null) {
                 Portability.delete(attributes);
                 attributes = null;
             }
+            // [NOCPP[
         }
+        // ]NOCPP]
     }
 
     public void loadState(Tokenizer other) throws SAXException {
         strBufLen = other.strBufLen;
         if (strBufLen > strBuf.length) {
             strBuf = new char[strBufLen];
         }
         System.arraycopy(other.strBuf, 0, strBuf, 0, strBufLen);
@@ -6994,18 +7000,16 @@ public class Tokenizer implements Locato
      */
     public void setEncodingDeclarationHandler(
             EncodingDeclarationHandler encodingDeclarationHandler) {
         this.encodingDeclarationHandler = encodingDeclarationHandler;
     }
     
     void destructor() {
         // The translator will write refcount tracing stuff here
-        Portability.delete(attributes);
-        attributes = null;
     }
     
     // [NOCPP[
     
     /**
      * Sets an offset to be added to the position reported to 
      * <code>TransitionHandler</code>.
      * 
--- a/parser/html/javasrc/TreeBuilder.java
+++ b/parser/html/javasrc/TreeBuilder.java
@@ -3022,19 +3022,19 @@ public abstract class TreeBuilder<T> imp
                     assert false;
                     break starttagloop; // Avoid infinite loop if the assertion
                                         // fails
             }
         }
         if (selfClosing) {
             errSelfClosing();
         }
-        // CPPONLY: if (mBuilder == null && attributes != HtmlAttributes.EMPTY_ATTRIBUTES) {
-        // CPPONLY:    Portability.delete(attributes);
-        // CPPONLY: }
+        if (attributes != HtmlAttributes.EMPTY_ATTRIBUTES) {
+            Portability.delete(attributes);
+        }
     }
 
     private void startTagTitleInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException {
         appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
         originalMode = mode;
         mode = TEXT;
         tokenizer.setStateAndEndTagExpectation(Tokenizer.RCDATA, elementName);
     }
@@ -5132,28 +5132,25 @@ public abstract class TreeBuilder<T> imp
 
     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);
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
             insertIntoFosterParent(elt);
         } else {
             appendElement(elt, current.node);
         }
-        StackNode<T> node = new StackNode<T>(elementName, elt, clone
+        StackNode<T> node = new StackNode<T>(elementName, elt, attributes.cloneAttributes(null)
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
         append(node);
         node.retain(); // append doesn't retain itself
     }
@@ -5209,32 +5206,30 @@ public abstract class TreeBuilder<T> imp
             throws SAXException {
         @Local String popName = elementName.name;
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML");
         if (elementName.isCustom()) {
             popName = checkPopName(popName);
         }
         // ]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);
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
             insertIntoFosterParent(elt);
         } else {
             appendElement(elt, current.node);
         }
+        boolean markAsHtmlIntegrationPoint = false;
+        if (ElementName.ANNOTATION_XML == elementName
+                && annotationXmlEncodingPermitsHtml(attributes)) {
+            markAsHtmlIntegrationPoint = true;
+        }
         StackNode<T> node = new StackNode<T>(elementName, elt, popName,
                 markAsHtmlIntegrationPoint
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
     }
--- a/parser/html/moz.build
+++ b/parser/html/moz.build
@@ -16,60 +16,55 @@ EXPORTS += [
     'nsAHtml5TreeBuilderState.h',
     'nsAHtml5TreeOpSink.h',
     'nsHtml5ArrayCopy.h',
     'nsHtml5AtomList.h',
     'nsHtml5Atoms.h',
     'nsHtml5AtomTable.h',
     'nsHtml5ByteReadable.h',
     'nsHtml5DependentUTF16Buffer.h',
-    'nsHtml5DocumentBuilder.h',
     'nsHtml5DocumentMode.h',
     'nsHtml5HtmlAttributes.h',
     'nsHtml5Macros.h',
     'nsHtml5MetaScanner.h',
     'nsHtml5MetaScannerHSupplement.h',
     'nsHtml5Module.h',
     'nsHtml5NamedCharacters.h',
     'nsHtml5NamedCharactersAccel.h',
-    'nsHtml5OplessBuilder.h',
     'nsHtml5OwningUTF16Buffer.h',
     'nsHtml5Parser.h',
     'nsHtml5PendingNotification.h',
     'nsHtml5PlainTextUtils.h',
     'nsHtml5Speculation.h',
     'nsHtml5SpeculativeLoad.h',
     'nsHtml5StreamParser.h',
     'nsHtml5StringParser.h',
     'nsHtml5SVGLoadDispatcher.h',
     'nsHtml5TreeOperation.h',
     'nsHtml5TreeOpExecutor.h',
     'nsHtml5TreeOpStage.h',
     'nsHtml5UTF16Buffer.h',
     'nsHtml5UTF16BufferHSupplement.h',
     'nsHtml5ViewSourceUtils.h',
-    'nsIContentHandle.h',
     'nsParserUtils.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsHtml5Atom.cpp',
     'nsHtml5Atoms.cpp',
     'nsHtml5AtomTable.cpp',
     'nsHtml5AttributeName.cpp',
     'nsHtml5DependentUTF16Buffer.cpp',
-    'nsHtml5DocumentBuilder.cpp',
     'nsHtml5ElementName.cpp',
     'nsHtml5Highlighter.cpp',
     'nsHtml5HtmlAttributes.cpp',
     'nsHtml5MetaScanner.cpp',
     'nsHtml5Module.cpp',
     'nsHtml5NamedCharacters.cpp',
     'nsHtml5NamedCharactersAccel.cpp',
-    'nsHtml5OplessBuilder.cpp',
     'nsHtml5OwningUTF16Buffer.cpp',
     'nsHtml5Parser.cpp',
     'nsHtml5PlainTextUtils.cpp',
     'nsHtml5Portability.cpp',
     'nsHtml5ReleasableAttributeName.cpp',
     'nsHtml5ReleasableElementName.cpp',
     'nsHtml5Speculation.cpp',
     'nsHtml5SpeculativeLoad.cpp',
--- a/parser/html/nsAHtml5TreeBuilderState.h
+++ b/parser/html/nsAHtml5TreeBuilderState.h
@@ -1,17 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsAHtml5TreeBuilderState_h
 #define nsAHtml5TreeBuilderState_h
 
-#include "nsIContentHandle.h"
-
 /**
  * Interface for exposing the internal state of the HTML5 tree builder.
  * For more documentation, please see
  * http://hg.mozilla.org/projects/htmlparser/file/tip/src/nu/validator/htmlparser/impl/StateSnapshot.java
  */
 class nsAHtml5TreeBuilderState {
   public:
   
@@ -22,21 +20,21 @@ class nsAHtml5TreeBuilderState {
     virtual jArray<int32_t,int32_t> getTemplateModeStack() = 0;
 
     virtual int32_t getStackLength() = 0;
 
     virtual int32_t getListOfActiveFormattingElementsLength() = 0;
 
     virtual int32_t getTemplateModeStackLength() = 0;
 
-    virtual nsIContentHandle* getFormPointer() = 0;
+    virtual nsIContent** getFormPointer() = 0;
     
-    virtual nsIContentHandle* getHeadPointer() = 0;
+    virtual nsIContent** getHeadPointer() = 0;
 
-    virtual nsIContentHandle* getDeepTreeSurrogateParent() = 0;
+    virtual nsIContent** getDeepTreeSurrogateParent() = 0;
 
     virtual int32_t getMode() = 0;
 
     virtual int32_t getOriginalMode() = 0;
 
     virtual bool isFramesetOk() = 0;
 
     virtual bool isNeedToDropLF() = 0;
--- a/parser/html/nsHtml5AtomTable.h
+++ b/parser/html/nsHtml5AtomTable.h
@@ -14,18 +14,17 @@
 class nsHtml5Atom;
 
 class nsHtml5AtomEntry : public nsStringHashKey
 {
   public:
     nsHtml5AtomEntry(KeyTypePointer aStr);
     nsHtml5AtomEntry(const nsHtml5AtomEntry& aOther);
     ~nsHtml5AtomEntry();
-    inline nsHtml5Atom* GetAtom()
-    {
+    inline nsHtml5Atom* GetAtom() {
       return mAtom;
     }
   private:
     nsAutoPtr<nsHtml5Atom> mAtom;
 };
 
 /**
  * nsHtml5AtomTable provides non-locking lookup and creation of atoms for 
@@ -80,24 +79,22 @@ class nsHtml5AtomTable
     /**
      * Obtains the atom for the given string in the scope of this atom table.
      */
     nsIAtom* GetAtom(const nsAString& aKey);
     
     /**
      * Empties the table.
      */
-    void Clear()
-    {
+    void Clear() {
       mTable.Clear();
     }
     
 #ifdef DEBUG
-    void SetPermittedLookupThread(nsIThread* aThread)
-    {
+    void SetPermittedLookupThread(nsIThread* aThread) {
       mPermittedLookupThread = aThread;
     }
 #endif  
   
   private:
     nsTHashtable<nsHtml5AtomEntry> mTable;
 #ifdef DEBUG
     nsCOMPtr<nsIThread>            mPermittedLookupThread;
--- a/parser/html/nsHtml5AttributeName.cpp
+++ b/parser/html/nsHtml5AttributeName.cpp
@@ -27,25 +27,24 @@
 
 #define nsHtml5AttributeName_cpp__
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 #include "nsHtml5Tokenizer.h"
 #include "nsHtml5TreeBuilder.h"
 #include "nsHtml5MetaScanner.h"
 #include "nsHtml5ElementName.h"
 #include "nsHtml5HtmlAttributes.h"
 #include "nsHtml5StackNode.h"
 #include "nsHtml5UTF16Buffer.h"
--- a/parser/html/nsHtml5AttributeName.h
+++ b/parser/html/nsHtml5AttributeName.h
@@ -28,25 +28,24 @@
 #ifndef nsHtml5AttributeName_h
 #define nsHtml5AttributeName_h
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 class nsHtml5StreamParser;
 
 class nsHtml5Tokenizer;
 class nsHtml5TreeBuilder;
 class nsHtml5MetaScanner;
 class nsHtml5ElementName;
 class nsHtml5HtmlAttributes;
deleted file mode 100644
--- a/parser/html/nsHtml5DocumentBuilder.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sw=2 et tw=78: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsHtml5DocumentBuilder.h"
-
-#include "nsIStyleSheetLinkingElement.h"
-#include "nsStyleLinkElement.h"
-#include "nsScriptLoader.h"
-#include "nsIHTMLDocument.h"
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED_1(nsHtml5DocumentBuilder, nsContentSink,
-                                     mOwnedElements)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsHtml5DocumentBuilder)
-NS_INTERFACE_MAP_END_INHERITING(nsContentSink)
-
-NS_IMPL_ADDREF_INHERITED(nsHtml5DocumentBuilder, nsContentSink)
-NS_IMPL_RELEASE_INHERITED(nsHtml5DocumentBuilder, nsContentSink)
-
-nsHtml5DocumentBuilder::nsHtml5DocumentBuilder(bool aRunsToCompletion)
-{
-  mRunsToCompletion = aRunsToCompletion;
-}
-
-nsresult
-nsHtml5DocumentBuilder::Init(nsIDocument* aDoc,
-                            nsIURI* aURI,
-                            nsISupports* aContainer,
-                            nsIChannel* aChannel)
-{
-  return nsContentSink::Init(aDoc, aURI, aContainer, aChannel);
-}
-
-nsHtml5DocumentBuilder::~nsHtml5DocumentBuilder()
-{
-}
-
-nsresult
-nsHtml5DocumentBuilder::MarkAsBroken(nsresult aReason)
-{
-  mBroken = aReason;
-  return aReason;
-}
-
-void
-nsHtml5DocumentBuilder::SetDocumentCharsetAndSource(nsACString& aCharset, int32_t aCharsetSource)
-{
-  if (mDocument) {
-    mDocument->SetDocumentCharacterSetSource(aCharsetSource);
-    mDocument->SetDocumentCharacterSet(aCharset);
-  }
-}
-
-void
-nsHtml5DocumentBuilder::UpdateStyleSheet(nsIContent* aElement)
-{
-  // Break out of the doc update created by Flush() to zap a runnable
-  // waiting to call UpdateStyleSheet without the right observer
-  EndDocUpdate();
-
-  if (MOZ_UNLIKELY(!mParser)) {
-    // EndDocUpdate ran stuff that called nsIParser::Terminate()
-    return;
-  }
-
-  nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aElement));
-  NS_ASSERTION(ssle, "Node didn't QI to style.");
-
-  ssle->SetEnableUpdates(true);
-
-  bool willNotify;
-  bool isAlternate;
-  nsresult rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this,
-                                       &willNotify,
-                                       &isAlternate);
-  if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mRunsToCompletion) {
-    ++mPendingSheetCount;
-    mScriptLoader->AddExecuteBlocker();
-  }
-
-  if (aElement->IsHTML(nsGkAtoms::link)) {
-    // look for <link rel="next" href="url">
-    nsAutoString relVal;
-    aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal);
-    if (!relVal.IsEmpty()) {
-      uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(relVal);
-      bool hasPrefetch = linkTypes & nsStyleLinkElement::ePREFETCH;
-      if (hasPrefetch || (linkTypes & nsStyleLinkElement::eNEXT)) {
-        nsAutoString hrefVal;
-        aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
-        if (!hrefVal.IsEmpty()) {
-          PrefetchHref(hrefVal, aElement, hasPrefetch);
-        }
-      }
-      if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
-        nsAutoString hrefVal;
-        aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
-        if (!hrefVal.IsEmpty()) {
-          PrefetchDNS(hrefVal);
-        }
-      }
-    }
-  }
-
-  // Re-open update
-  BeginDocUpdate();
-}
-
-void
-nsHtml5DocumentBuilder::SetDocumentMode(nsHtml5DocumentMode m)
-{
-  nsCompatibility mode = eCompatibility_NavQuirks;
-  switch (m) {
-    case STANDARDS_MODE:
-      mode = eCompatibility_FullStandards;
-      break;
-    case ALMOST_STANDARDS_MODE:
-      mode = eCompatibility_AlmostStandards;
-      break;
-    case QUIRKS_MODE:
-      mode = eCompatibility_NavQuirks;
-      break;
-  }
-  nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(mDocument);
-  NS_ASSERTION(htmlDocument, "Document didn't QI into HTML document.");
-  htmlDocument->SetCompatibilityMode(mode);
-}
-
-// nsContentSink overrides
-
-void
-nsHtml5DocumentBuilder::UpdateChildCounts()
-{
-  // No-op
-}
-
-nsresult
-nsHtml5DocumentBuilder::FlushTags()
-{
-  return NS_OK;
-}
deleted file mode 100644
--- a/parser/html/nsHtml5DocumentBuilder.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sw=2 et tw=78: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsHtml5DocumentBuilder_h
-#define nsHtml5DocumentBuilder_h
-
-#include "nsHtml5PendingNotification.h"
-#include "nsContentSink.h"
-#include "nsHtml5DocumentMode.h"
-#include "nsIDocument.h"
-
-typedef nsIContent* nsIContentPtr;
-
-enum eHtml5FlushState {
-  eNotFlushing = 0,  // not flushing
-  eInFlush = 1,      // the Flush() method is on the call stack
-  eInDocUpdate = 2,  // inside an update batch on the document
-  eNotifying = 3     // flushing pending append notifications
-};
-
-class nsHtml5DocumentBuilder : public nsContentSink
-{
-public:
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHtml5DocumentBuilder,
-                                           nsContentSink)
-
-  NS_DECL_ISUPPORTS_INHERITED
-
-  inline void HoldElement(nsIContent* aContent)
-  {
-    mOwnedElements.AppendElement(aContent);
-  }
-
-  inline bool HaveNotified(nsIContent* aNode)
-  {
-    NS_PRECONDITION(aNode, "HaveNotified called with null argument.");
-    const nsHtml5PendingNotification* start = mPendingNotifications.Elements();
-    const nsHtml5PendingNotification* end = start + mPendingNotifications.Length();
-    for (;;) {
-      nsIContent* parent = aNode->GetParent();
-      if (!parent) {
-        return true;
-      }
-      for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) {
-        if (iter->Contains(parent)) {
-          return iter->HaveNotifiedIndex(parent->IndexOf(aNode));
-        }
-      }
-      aNode = parent;
-    }
-  }
-
-  void PostPendingAppendNotification(nsIContent* aParent, nsIContent* aChild)
-  {
-    bool newParent = true;
-    const nsIContentPtr* first = mElementsSeenInThisAppendBatch.Elements();
-    const nsIContentPtr* last = first + mElementsSeenInThisAppendBatch.Length() - 1;
-    for (const nsIContentPtr* iter = last; iter >= first; --iter) {
-#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
-      sAppendBatchSlotsExamined++;
-#endif
-      if (*iter == aParent) {
-        newParent = false;
-        break;
-      }
-    }
-    if (aChild->IsElement()) {
-      mElementsSeenInThisAppendBatch.AppendElement(aChild);
-    }
-    mElementsSeenInThisAppendBatch.AppendElement(aParent);
-    if (newParent) {
-      mPendingNotifications.AppendElement(aParent);
-    }
-#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
-    sAppendBatchExaminations++;
-#endif
-  }
-
-  void FlushPendingAppendNotifications()
-  {
-    NS_PRECONDITION(mFlushState == eInDocUpdate, "Notifications flushed outside update");
-    mFlushState = eNotifying;
-    const nsHtml5PendingNotification* start = mPendingNotifications.Elements();
-    const nsHtml5PendingNotification* end = start + mPendingNotifications.Length();
-    for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) {
-      iter->Fire();
-    }
-    mPendingNotifications.Clear();
-#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
-    if (mElementsSeenInThisAppendBatch.Length() > sAppendBatchMaxSize) {
-      sAppendBatchMaxSize = mElementsSeenInThisAppendBatch.Length();
-    }
-#endif
-    mElementsSeenInThisAppendBatch.Clear();
-    NS_ASSERTION(mFlushState == eNotifying, "mFlushState out of sync");
-    mFlushState = eInDocUpdate;
-  }
-
-  nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
-                nsISupports* aContainer, nsIChannel* aChannel);
-
-  // Getters and setters for fields from nsContentSink
-  nsIDocument* GetDocument()
-  {
-    return mDocument;
-  }
-
-  nsNodeInfoManager* GetNodeInfoManager()
-  {
-    return mNodeInfoManager;
-  }
-
-  /**
-   * Marks this parser as broken and tells the stream parser (if any) to
-   * terminate.
-   *
-   * @return aReason for convenience
-   */
-  virtual nsresult MarkAsBroken(nsresult aReason);
-
-  /**
-   * Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0)
-   * value if broken.
-   */
-  inline nsresult IsBroken()
-  {
-    return mBroken;
-  }
-
-  inline void BeginDocUpdate()
-  {
-    NS_PRECONDITION(mFlushState == eInFlush, "Tried to double-open update.");
-    NS_PRECONDITION(mParser, "Started update without parser.");
-    mFlushState = eInDocUpdate;
-    mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
-  }
-
-  inline void EndDocUpdate()
-  {
-    NS_PRECONDITION(mFlushState != eNotifying, "mFlushState out of sync");
-    if (mFlushState == eInDocUpdate) {
-      FlushPendingAppendNotifications();
-      mFlushState = eInFlush;
-      mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
-    }
-  }
-
-  void SetDocumentCharsetAndSource(nsACString& aCharset, int32_t aCharsetSource);
-
-  /**
-   * Sets up style sheet load / parse
-   */
-  void UpdateStyleSheet(nsIContent* aElement);
-
-  void SetDocumentMode(nsHtml5DocumentMode m);
-
-  void SetNodeInfoManager(nsNodeInfoManager* aManager)
-  {
-    mNodeInfoManager = aManager;
-  }
-
-  // nsContentSink methods
-  virtual void UpdateChildCounts();
-  virtual nsresult FlushTags();
-
-protected:
-  inline void SetAppendBatchCapacity(uint32_t aCapacity)
-  {
-    mElementsSeenInThisAppendBatch.SetCapacity(aCapacity);
-  }
-
-  nsHtml5DocumentBuilder(bool aRunsToCompletion);
-  virtual ~nsHtml5DocumentBuilder();
-
-private:
-  nsTArray<nsHtml5PendingNotification> mPendingNotifications;
-  nsTArray<nsIContentPtr>              mElementsSeenInThisAppendBatch;
-protected:
-  nsTArray<nsCOMPtr<nsIContent> >      mOwnedElements;
-  /**
-   * Non-NS_OK if this parser should refuse to process any more input.
-   * For example, the parser needs to be marked as broken if it drops some
-   * input due to a memory allocation failure. In such a case, the whole
-   * parser needs to be marked as broken, because some input has been lost
-   * and parsing more input could lead to a DOM where pieces of HTML source
-   * that weren't supposed to become scripts become scripts.
-   *
-   * Since NS_OK is actually 0, zeroing operator new takes care of
-   * initializing this.
-   */
-  nsresult                             mBroken;
-  eHtml5FlushState                     mFlushState;
-};
-
-#endif // nsHtml5DocumentBuilder_h
--- a/parser/html/nsHtml5ElementName.cpp
+++ b/parser/html/nsHtml5ElementName.cpp
@@ -27,25 +27,24 @@
 
 #define nsHtml5ElementName_cpp__
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 #include "nsHtml5Tokenizer.h"
 #include "nsHtml5TreeBuilder.h"
 #include "nsHtml5MetaScanner.h"
 #include "nsHtml5AttributeName.h"
 #include "nsHtml5HtmlAttributes.h"
 #include "nsHtml5StackNode.h"
 #include "nsHtml5UTF16Buffer.h"
--- a/parser/html/nsHtml5ElementName.h
+++ b/parser/html/nsHtml5ElementName.h
@@ -28,25 +28,24 @@
 #ifndef nsHtml5ElementName_h
 #define nsHtml5ElementName_h
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 class nsHtml5StreamParser;
 
 class nsHtml5Tokenizer;
 class nsHtml5TreeBuilder;
 class nsHtml5MetaScanner;
 class nsHtml5AttributeName;
 class nsHtml5HtmlAttributes;
--- a/parser/html/nsHtml5HtmlAttributes.cpp
+++ b/parser/html/nsHtml5HtmlAttributes.cpp
@@ -28,25 +28,24 @@
 
 #define nsHtml5HtmlAttributes_cpp__
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 #include "nsHtml5Tokenizer.h"
 #include "nsHtml5TreeBuilder.h"
 #include "nsHtml5MetaScanner.h"
 #include "nsHtml5AttributeName.h"
 #include "nsHtml5ElementName.h"
 #include "nsHtml5StackNode.h"
 #include "nsHtml5UTF16Buffer.h"
--- a/parser/html/nsHtml5HtmlAttributes.h
+++ b/parser/html/nsHtml5HtmlAttributes.h
@@ -29,25 +29,24 @@
 #ifndef nsHtml5HtmlAttributes_h
 #define nsHtml5HtmlAttributes_h
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 class nsHtml5StreamParser;
 
 class nsHtml5Tokenizer;
 class nsHtml5TreeBuilder;
 class nsHtml5MetaScanner;
 class nsHtml5AttributeName;
 class nsHtml5ElementName;
--- a/parser/html/nsHtml5MetaScanner.cpp
+++ b/parser/html/nsHtml5MetaScanner.cpp
@@ -28,25 +28,24 @@
 
 #define nsHtml5MetaScanner_cpp__
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 #include "nsHtml5Tokenizer.h"
 #include "nsHtml5TreeBuilder.h"
 #include "nsHtml5AttributeName.h"
 #include "nsHtml5ElementName.h"
 #include "nsHtml5HtmlAttributes.h"
 #include "nsHtml5StackNode.h"
 #include "nsHtml5UTF16Buffer.h"
--- a/parser/html/nsHtml5MetaScanner.h
+++ b/parser/html/nsHtml5MetaScanner.h
@@ -29,25 +29,24 @@
 #ifndef nsHtml5MetaScanner_h
 #define nsHtml5MetaScanner_h
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 class nsHtml5StreamParser;
 
 class nsHtml5Tokenizer;
 class nsHtml5TreeBuilder;
 class nsHtml5AttributeName;
 class nsHtml5ElementName;
 class nsHtml5HtmlAttributes;
--- a/parser/html/nsHtml5MetaScannerHSupplement.h
+++ b/parser/html/nsHtml5MetaScannerHSupplement.h
@@ -1,12 +1,11 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  
 private:
   nsCString mCharset;
-  inline int32_t read()
-  {
+  inline int32_t read() {
     return readable->read();
   }
 public:
   void sniff(nsHtml5ByteReadable* bytes, nsACString& charset);
deleted file mode 100644
--- a/parser/html/nsHtml5OplessBuilder.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sw=2 et tw=78: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsHtml5OplessBuilder.h"
-
-#include "nsScriptLoader.h"
-#include "mozilla/css/Loader.h"
-#include "nsIDocShell.h"
-#include "nsIHTMLDocument.h"
-
-nsHtml5OplessBuilder::nsHtml5OplessBuilder()
- : nsHtml5DocumentBuilder(true)
-{
-}
-
-nsHtml5OplessBuilder::~nsHtml5OplessBuilder()
-{
-}
-
-void
-nsHtml5OplessBuilder::Start()
-{
-  mFlushState = eInFlush;
-  BeginDocUpdate();
-}
-
-void
-nsHtml5OplessBuilder::Finish()
-{
-  EndDocUpdate();
-  DropParserAndPerfHint();
-  mScriptLoader = nullptr;
-  mDocument = nullptr;
-  mNodeInfoManager = nullptr;
-  mCSSLoader = nullptr;
-  mDocumentURI = nullptr;
-  mDocShell = nullptr;
-  mOwnedElements.Clear();
-  mFlushState = eNotFlushing;
-}
-
-void
-nsHtml5OplessBuilder::SetParser(nsParserBase* aParser)
-{
-  mParser = aParser;
-}
deleted file mode 100644
--- a/parser/html/nsHtml5OplessBuilder.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sw=2 et tw=78: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsHtml5OplessBuilder_h
-#define nsHtml5OplessBuilder_h
-
-#include "nsHtml5DocumentBuilder.h"
-
-class nsParserBase;
-
-/**
- * This class implements a minimal subclass of nsHtml5DocumentBuilder that
- * works when tree operation queues that are part of the off-the-main-thread
- * parsing machinery are not used and, therefore, nsHtml5TreeOpExecutor is
- * not used.
- *
- * This class is mostly responsible for wrapping tree building in an update
- * batch and resetting various fields in nsContentSink upon finishing.
- */
-class nsHtml5OplessBuilder : public nsHtml5DocumentBuilder
-{
-public:
-  NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-
-  nsHtml5OplessBuilder();
-  ~nsHtml5OplessBuilder();
-  void Start();
-  void Finish();
-  void SetParser(nsParserBase* aParser);
-};
-
-#endif // nsHtml5OplessBuilder_h
--- a/parser/html/nsHtml5Parser.h
+++ b/parser/html/nsHtml5Parser.h
@@ -232,30 +232,28 @@ class nsHtml5Parser : public nsIParser,
                         nsIChannel* aChannel);
 
     inline nsHtml5Tokenizer* GetTokenizer() {
       return mTokenizer;
     }
 
     void InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState, int32_t aLine);
 
-    void DropStreamParser()
-    {
+    void DropStreamParser() {
       if (mStreamParser) {
         mStreamParser->DropTimer();
         mStreamParser = nullptr;
       }
     }
     
     void StartTokenizer(bool aScriptingEnabled);
     
     void ContinueAfterFailedCharsetSwitch();
 
-    nsHtml5StreamParser* GetStreamParser()
-    {
+    nsHtml5StreamParser* GetStreamParser() {
       return mStreamParser;
     }
 
     /**
      * Parse until pending data is exhausted or a script blocks the parser
      */
     void ParseUntilBlocked();
 
--- a/parser/html/nsHtml5PendingNotification.h
+++ b/parser/html/nsHtml5PendingNotification.h
@@ -14,34 +14,30 @@ class nsHtml5PendingNotification {
 
     nsHtml5PendingNotification(nsIContent* aParent)
      : mParent(aParent),
        mChildCount(aParent->GetChildCount() - 1)
     {
       MOZ_COUNT_CTOR(nsHtml5PendingNotification);
     }
 
-    ~nsHtml5PendingNotification()
-    {
+    ~nsHtml5PendingNotification() {
       MOZ_COUNT_DTOR(nsHtml5PendingNotification);
     }
 
-    inline void Fire()
-    {
+    inline void Fire() {
       nsNodeUtils::ContentAppended(mParent, mParent->GetChildAt(mChildCount),
                                    mChildCount);
     }
 
-    inline bool Contains(nsIContent* aNode)
-    {
+    inline bool Contains(nsIContent* aNode) {
       return !!(mParent == aNode);
     }
     
-    inline bool HaveNotifiedIndex(uint32_t index)
-    {
+    inline bool HaveNotifiedIndex(uint32_t index) {
       return index < mChildCount;
     }
 
   private:
     /**
      * An element
      */
     nsIContent* mParent;
--- a/parser/html/nsHtml5Portability.h
+++ b/parser/html/nsHtml5Portability.h
@@ -28,25 +28,24 @@
 #ifndef nsHtml5Portability_h
 #define nsHtml5Portability_h
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 class nsHtml5StreamParser;
 
 class nsHtml5Tokenizer;
 class nsHtml5TreeBuilder;
 class nsHtml5MetaScanner;
 class nsHtml5AttributeName;
 class nsHtml5ElementName;
--- a/parser/html/nsHtml5Speculation.h
+++ b/parser/html/nsHtml5Speculation.h
@@ -18,33 +18,29 @@ class nsHtml5Speculation MOZ_FINAL : pub
   public:
     nsHtml5Speculation(nsHtml5OwningUTF16Buffer* aBuffer,
                        int32_t aStart, 
                        int32_t aStartLineNumber, 
                        nsAHtml5TreeBuilderState* aSnapshot);
     
     ~nsHtml5Speculation();
 
-    nsHtml5OwningUTF16Buffer* GetBuffer()
-    {
+    nsHtml5OwningUTF16Buffer* GetBuffer() {
       return mBuffer;
     }
     
-    int32_t GetStart()
-    {
+    int32_t GetStart() {
       return mStart;
     }
 
-    int32_t GetStartLineNumber()
-    {
+    int32_t GetStartLineNumber() {
       return mStartLineNumber;
     }
     
-    nsAHtml5TreeBuilderState* GetSnapshot()
-    {
+    nsAHtml5TreeBuilderState* GetSnapshot() {
       return mSnapshot;
     }
 
     /**
      * Flush the operations from the tree operations from the argument
      * queue unconditionally.
      */
     virtual void MoveOpsFrom(nsTArray<nsHtml5TreeOperation>& aOpQueue);
--- a/parser/html/nsHtml5SpeculativeLoad.h
+++ b/parser/html/nsHtml5SpeculativeLoad.h
@@ -22,53 +22,49 @@ enum eHtml5SpeculativeLoad {
   eSpeculativeLoadSetDocumentCharset
 };
 
 class nsHtml5SpeculativeLoad {
   public:
     nsHtml5SpeculativeLoad();
     ~nsHtml5SpeculativeLoad();
     
-    inline void InitBase(const nsAString& aUrl)
-    {
+    inline void InitBase(const nsAString& aUrl) {
       NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
                       "Trying to reinitialize a speculative load!");
       mOpCode = eSpeculativeLoadBase;
       mUrl.Assign(aUrl);
     }
 
     inline void InitImage(const nsAString& aUrl,
-                          const nsAString& aCrossOrigin)
-    {
+                          const nsAString& aCrossOrigin) {
       NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
                       "Trying to reinitialize a speculative load!");
       mOpCode = eSpeculativeLoadImage;
       mUrl.Assign(aUrl);
       mCrossOrigin.Assign(aCrossOrigin);
     }
 
     inline void InitScript(const nsAString& aUrl,
                            const nsAString& aCharset,
                            const nsAString& aType,
                            const nsAString& aCrossOrigin,
-                           bool aParserInHead)
-    {
+                           bool aParserInHead) {
       NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
                       "Trying to reinitialize a speculative load!");
       mOpCode = aParserInHead ?
           eSpeculativeLoadScriptFromHead : eSpeculativeLoadScript;
       mUrl.Assign(aUrl);
       mCharset.Assign(aCharset);
       mTypeOrCharsetSource.Assign(aType);
       mCrossOrigin.Assign(aCrossOrigin);
     }
     
     inline void InitStyle(const nsAString& aUrl, const nsAString& aCharset,
-			  const nsAString& aCrossOrigin)
-    {
+			  const nsAString& aCrossOrigin) {
       NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
                       "Trying to reinitialize a speculative load!");
       mOpCode = eSpeculativeLoadStyle;
       mUrl.Assign(aUrl);
       mCharset.Assign(aCharset);
       mCrossOrigin.Assign(aCrossOrigin);
     }
 
@@ -78,18 +74,17 @@ class nsHtml5SpeculativeLoad {
      * before the manifest, so the situation of having to undo a manifest due
      * to document.write() never arises. The reason why a parser
      * thread-discovered manifest gets loaded via the speculative load queue
      * as opposed to tree operation queue is that the manifest must get
      * processed before any actual speculative loads such as scripts. Thus,
      * manifests seen by the parser thread have to maintain the queue order
      * relative to true speculative loads. See bug 541079.
      */
-    inline void InitManifest(const nsAString& aUrl)
-    {
+    inline void InitManifest(const nsAString& aUrl) {
       NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
                       "Trying to reinitialize a speculative load!");
       mOpCode = eSpeculativeLoadManifest;
       mUrl.Assign(aUrl);
     }
 
     /**
      * "Speculative" charset setting isn't truly speculative. If the charset
@@ -97,18 +92,17 @@ class nsHtml5SpeculativeLoad {
      * a late meta cause a reload. The reason why a parser
      * thread-discovered charset gets communicated via the speculative load
      * queue as opposed to tree operation queue is that the charset change
      * must get processed before any actual speculative loads such as style
      * sheets. Thus, encoding decisions by the parser thread have to maintain
      * the queue order relative to true speculative loads. See bug 675499.
      */
     inline void InitSetDocumentCharset(nsACString& aCharset,
-                                       int32_t aCharsetSource)
-    {
+                                       int32_t aCharsetSource) {
       NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
                       "Trying to reinitialize a speculative load!");
       mOpCode = eSpeculativeLoadSetDocumentCharset;
       CopyUTF8toUTF16(aCharset, mCharset);
       mTypeOrCharsetSource.Assign((char16_t)aCharsetSource);
     }
 
     void Perform(nsHtml5TreeOpExecutor* aExecutor);
--- a/parser/html/nsHtml5StackNode.cpp
+++ b/parser/html/nsHtml5StackNode.cpp
@@ -28,25 +28,24 @@
 
 #define nsHtml5StackNode_cpp__
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 #include "nsHtml5Tokenizer.h"
 #include "nsHtml5TreeBuilder.h"
 #include "nsHtml5MetaScanner.h"
 #include "nsHtml5AttributeName.h"
 #include "nsHtml5ElementName.h"
 #include "nsHtml5HtmlAttributes.h"
 #include "nsHtml5UTF16Buffer.h"
@@ -81,84 +80,84 @@ nsHtml5StackNode::isFosterParenting()
 
 bool 
 nsHtml5StackNode::isHtmlIntegrationPoint()
 {
   return (flags & NS_HTML5ELEMENT_NAME_HTML_INTEGRATION_POINT);
 }
 
 
-nsHtml5StackNode::nsHtml5StackNode(int32_t flags, int32_t ns, nsIAtom* name, nsIContentHandle* node, nsIAtom* popName, nsHtml5HtmlAttributes* attributes)
+nsHtml5StackNode::nsHtml5StackNode(int32_t flags, int32_t ns, nsIAtom* name, nsIContent** node, nsIAtom* popName, nsHtml5HtmlAttributes* attributes)
   : flags(flags),
     name(name),
     popName(popName),
     ns(ns),
     node(node),
     attributes(attributes),
     refcount(1)
 {
   MOZ_COUNT_CTOR(nsHtml5StackNode);
 }
 
 
-nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node)
+nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContent** node)
   : flags(elementName->getFlags()),
     name(elementName->name),
     popName(elementName->name),
     ns(kNameSpaceID_XHTML),
     node(node),
     attributes(nullptr),
     refcount(1)
 {
   MOZ_COUNT_CTOR(nsHtml5StackNode);
   MOZ_ASSERT(!elementName->isCustom(), "Don't use this constructor for custom elements.");
 }
 
 
-nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsHtml5HtmlAttributes* attributes)
+nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContent** node, nsHtml5HtmlAttributes* attributes)
   : flags(elementName->getFlags()),
     name(elementName->name),
     popName(elementName->name),
     ns(kNameSpaceID_XHTML),
     node(node),
     attributes(attributes),
     refcount(1)
 {
   MOZ_COUNT_CTOR(nsHtml5StackNode);
   MOZ_ASSERT(!elementName->isCustom(), "Don't use this constructor for custom elements.");
 }
 
 
-nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName)
+nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContent** node, nsIAtom* popName)
   : flags(elementName->getFlags()),
     name(elementName->name),
     popName(popName),
     ns(kNameSpaceID_XHTML),
     node(node),
     attributes(nullptr),
     refcount(1)
 {
   MOZ_COUNT_CTOR(nsHtml5StackNode);
 }
 
 
-nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIAtom* popName, nsIContentHandle* node)
+nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIAtom* popName, nsIContent** node)
   : flags(prepareSvgFlags(elementName->getFlags())),
     name(elementName->name),
     popName(popName),
     ns(kNameSpaceID_SVG),
     node(node),
     attributes(nullptr),
     refcount(1)
 {
   MOZ_COUNT_CTOR(nsHtml5StackNode);
 }
 
 
-nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName, bool markAsIntegrationPoint)
+nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContent** node, nsIAtom* popName, bool markAsIntegrationPoint)
   : flags(prepareMathFlags(elementName->getFlags(), markAsIntegrationPoint)),
     name(elementName->name),
     popName(popName),
     ns(kNameSpaceID_MathML),
     node(node),
     attributes(nullptr),
     refcount(1)
 {
--- a/parser/html/nsHtml5StackNode.h
+++ b/parser/html/nsHtml5StackNode.h
@@ -29,25 +29,24 @@
 #ifndef nsHtml5StackNode_h
 #define nsHtml5StackNode_h
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 class nsHtml5StreamParser;
 
 class nsHtml5Tokenizer;
 class nsHtml5TreeBuilder;
 class nsHtml5MetaScanner;
 class nsHtml5AttributeName;
 class nsHtml5ElementName;
@@ -59,37 +58,37 @@ class nsHtml5Portability;
 
 class nsHtml5StackNode
 {
   public:
     int32_t flags;
     nsIAtom* name;
     nsIAtom* popName;
     int32_t ns;
-    nsIContentHandle* node;
+    nsIContent** node;
     nsHtml5HtmlAttributes* attributes;
   private:
     int32_t refcount;
   public:
     inline int32_t getFlags()
     {
       return flags;
     }
 
     int32_t getGroup();
     bool isScoping();
     bool isSpecial();
     bool isFosterParenting();
     bool isHtmlIntegrationPoint();
-    nsHtml5StackNode(int32_t flags, int32_t ns, nsIAtom* name, nsIContentHandle* node, nsIAtom* popName, nsHtml5HtmlAttributes* attributes);
-    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node);
-    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsHtml5HtmlAttributes* attributes);
-    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName);
-    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIAtom* popName, nsIContentHandle* node);
-    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName, bool markAsIntegrationPoint);
+    nsHtml5StackNode(int32_t flags, int32_t ns, nsIAtom* name, nsIContent** node, nsIAtom* popName, nsHtml5HtmlAttributes* attributes);
+    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContent** node);
+    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContent** node, nsHtml5HtmlAttributes* attributes);
+    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContent** node, nsIAtom* popName);
+    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIAtom* popName, nsIContent** node);
+    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContent** node, nsIAtom* popName, bool markAsIntegrationPoint);
   private:
     static int32_t prepareSvgFlags(int32_t flags);
     static int32_t prepareMathFlags(int32_t flags, bool markAsIntegrationPoint);
   public:
     ~nsHtml5StackNode();
     void dropAttributes();
     void retain();
     void release();
--- a/parser/html/nsHtml5StateSnapshot.cpp
+++ b/parser/html/nsHtml5StateSnapshot.cpp
@@ -27,40 +27,39 @@
 
 #define nsHtml5StateSnapshot_cpp__
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 #include "nsHtml5Tokenizer.h"
 #include "nsHtml5TreeBuilder.h"
 #include "nsHtml5MetaScanner.h"
 #include "nsHtml5AttributeName.h"
 #include "nsHtml5ElementName.h"
 #include "nsHtml5HtmlAttributes.h"
 #include "nsHtml5StackNode.h"
 #include "nsHtml5UTF16Buffer.h"
 #include "nsHtml5Portability.h"
 
 #include "nsHtml5StateSnapshot.h"
 
 
-nsHtml5StateSnapshot::nsHtml5StateSnapshot(jArray<nsHtml5StackNode*,int32_t> stack, jArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements, jArray<int32_t,int32_t> templateModeStack, nsIContentHandle* formPointer, nsIContentHandle* headPointer, nsIContentHandle* deepTreeSurrogateParent, int32_t mode, int32_t originalMode, bool framesetOk, bool needToDropLF, bool quirks)
+nsHtml5StateSnapshot::nsHtml5StateSnapshot(jArray<nsHtml5StackNode*,int32_t> stack, jArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements, jArray<int32_t,int32_t> templateModeStack, nsIContent** formPointer, nsIContent** headPointer, nsIContent** deepTreeSurrogateParent, int32_t mode, int32_t originalMode, bool framesetOk, bool needToDropLF, bool quirks)
   : stack(stack),
     listOfActiveFormattingElements(listOfActiveFormattingElements),
     templateModeStack(templateModeStack),
     formPointer(formPointer),
     headPointer(headPointer),
     deepTreeSurrogateParent(deepTreeSurrogateParent),
     mode(mode),
     originalMode(originalMode),
@@ -84,29 +83,29 @@ nsHtml5StateSnapshot::getTemplateModeSta
 }
 
 jArray<nsHtml5StackNode*,int32_t> 
 nsHtml5StateSnapshot::getListOfActiveFormattingElements()
 {
   return listOfActiveFormattingElements;
 }
 
-nsIContentHandle* 
+nsIContent** 
 nsHtml5StateSnapshot::getFormPointer()
 {
   return formPointer;
 }
 
-nsIContentHandle* 
+nsIContent** 
 nsHtml5StateSnapshot::getHeadPointer()
 {
   return headPointer;
 }
 
-nsIContentHandle* 
+nsIContent** 
 nsHtml5StateSnapshot::getDeepTreeSurrogateParent()
 {
   return deepTreeSurrogateParent;
 }
 
 int32_t 
 nsHtml5StateSnapshot::getMode()
 {
--- a/parser/html/nsHtml5StateSnapshot.h
+++ b/parser/html/nsHtml5StateSnapshot.h
@@ -28,25 +28,24 @@
 #ifndef nsHtml5StateSnapshot_h
 #define nsHtml5StateSnapshot_h
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 class nsHtml5StreamParser;
 
 class nsHtml5Tokenizer;
 class nsHtml5TreeBuilder;
 class nsHtml5MetaScanner;
 class nsHtml5AttributeName;
 class nsHtml5ElementName;
@@ -56,32 +55,32 @@ class nsHtml5Portability;
 
 
 class nsHtml5StateSnapshot : public nsAHtml5TreeBuilderState
 {
   private:
     autoJArray<nsHtml5StackNode*,int32_t> stack;
     autoJArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements;
     autoJArray<int32_t,int32_t> templateModeStack;
-    nsIContentHandle* formPointer;
-    nsIContentHandle* headPointer;
-    nsIContentHandle* deepTreeSurrogateParent;
+    nsIContent** formPointer;
+    nsIContent** headPointer;
+    nsIContent** deepTreeSurrogateParent;
     int32_t mode;
     int32_t originalMode;
     bool framesetOk;
     bool needToDropLF;
     bool quirks;
   public:
-    nsHtml5StateSnapshot(jArray<nsHtml5StackNode*,int32_t> stack, jArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements, jArray<int32_t,int32_t> templateModeStack, nsIContentHandle* formPointer, nsIContentHandle* headPointer, nsIContentHandle* deepTreeSurrogateParent, int32_t mode, int32_t originalMode, bool framesetOk, bool needToDropLF, bool quirks);
+    nsHtml5StateSnapshot(jArray<nsHtml5StackNode*,int32_t> stack, jArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements, jArray<int32_t,int32_t> templateModeStack, nsIContent** formPointer, nsIContent** headPointer, nsIContent** deepTreeSurrogateParent, int32_t mode, int32_t originalMode, bool framesetOk, bool needToDropLF, bool quirks);
     jArray<nsHtml5StackNode*,int32_t> getStack();
     jArray<int32_t,int32_t> getTemplateModeStack();
     jArray<nsHtml5StackNode*,int32_t> getListOfActiveFormattingElements();
-    nsIContentHandle* getFormPointer();
-    nsIContentHandle* getHeadPointer();
-    nsIContentHandle* getDeepTreeSurrogateParent();
+    nsIContent** getFormPointer();
+    nsIContent** getHeadPointer();
+    nsIContent** getDeepTreeSurrogateParent();
     int32_t getMode();
     int32_t getOriginalMode();
     bool isFramesetOk();
     bool isNeedToDropLF();
     bool isQuirks();
     int32_t getListOfActiveFormattingElementsLength();
     int32_t getStackLength();
     int32_t getTemplateModeStackLength();
--- a/parser/html/nsHtml5StreamParser.h
+++ b/parser/html/nsHtml5StreamParser.h
@@ -176,18 +176,17 @@ class nsHtml5StreamParser : public nsISt
                               nsHtml5TreeBuilder* aTreeBuilder,
                               bool aLastWasCR);
 
     /**
      * Continues the stream parser if the charset switch failed.
      */
     void ContinueAfterFailedCharsetSwitch();
 
-    void Terminate()
-    {
+    void Terminate() {
       mozilla::MutexAutoLock autoLock(mTerminatedMutex);
       mTerminated = true;
     }
     
     void DropTimer();
 
     /**
      * Sets mCharset and mCharsetSource appropriately for the XML View Source
@@ -216,24 +215,22 @@ class nsHtml5StreamParser : public nsISt
     void MarkAsBroken();
 
     /**
      * Marks the stream parser as interrupted. If you ever add calls to this
      * method, be sure to review Uninterrupt usage very, very carefully to
      * avoid having a previous in-flight runnable cancel your Interrupt()
      * call on the other thread too soon.
      */
-    void Interrupt()
-    {
+    void Interrupt() {
       mozilla::MutexAutoLock autoLock(mTerminatedMutex);
       mInterrupted = true;
     }
 
-    void Uninterrupt()
-    {
+    void Uninterrupt() {
       NS_ASSERTION(IsParserThread(), "Wrong thread!");
       mTokenizerMutex.AssertCurrentThreadOwns();
       // Not acquiring mTerminatedMutex because mTokenizerMutex is already
       // held at this point and is already stronger.
       mInterrupted = false;      
     }
 
     /**
@@ -250,33 +247,30 @@ class nsHtml5StreamParser : public nsISt
 
     static NS_METHOD CopySegmentsToParser(nsIInputStream *aInStream,
                                           void *aClosure,
                                           const char *aFromSegment,
                                           uint32_t aToOffset,
                                           uint32_t aCount,
                                           uint32_t *aWriteCount);
 
-    bool IsTerminatedOrInterrupted()
-    {
+    bool IsTerminatedOrInterrupted() {
       mozilla::MutexAutoLock autoLock(mTerminatedMutex);
       return mTerminated || mInterrupted;
     }
 
-    bool IsTerminated()
-    {
+    bool IsTerminated() {
       mozilla::MutexAutoLock autoLock(mTerminatedMutex);
       return mTerminated;
     }
 
     /**
      * True when there is a Unicode decoder already
      */
-    inline bool HasDecoder()
-    {
+    inline bool HasDecoder() {
       return !!mUnicodeDecoder;
     }
 
     /**
      * Push bytes from network when there is no Unicode decoder yet
      */
     nsresult SniffStreamBytes(const uint8_t* aFromSegment,
                               uint32_t aCount,
--- a/parser/html/nsHtml5StringParser.cpp
+++ b/parser/html/nsHtml5StringParser.cpp
@@ -9,18 +9,18 @@
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsHtml5DependentUTF16Buffer.h"
 
 NS_IMPL_ISUPPORTS0(nsHtml5StringParser)
 
 nsHtml5StringParser::nsHtml5StringParser()
-  : mBuilder(new nsHtml5OplessBuilder())
-  , mTreeBuilder(new nsHtml5TreeBuilder(mBuilder))
+  : mExecutor(new nsHtml5TreeOpExecutor(true))
+  , mTreeBuilder(new nsHtml5TreeBuilder(mExecutor, nullptr))
   , mTokenizer(new nsHtml5Tokenizer(mTreeBuilder, false))
 {
   MOZ_COUNT_CTOR(nsHtml5StringParser);
   mTokenizer->setInterner(&mAtomTable);
 }
 
 nsHtml5StringParser::~nsHtml5StringParser()
 {
@@ -37,35 +37,37 @@ nsHtml5StringParser::ParseFragment(const
 {
   NS_ENSURE_TRUE(aSourceBuffer.Length() <= INT32_MAX,
                  NS_ERROR_OUT_OF_MEMORY);
 
   nsIDocument* doc = aTargetNode->OwnerDoc();
   nsIURI* uri = doc->GetDocumentURI();
   NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);
 
+  nsIContent* target = aTargetNode;
   mTreeBuilder->setFragmentContext(aContextLocalName,
                                    aContextNamespace,
-                                   aTargetNode,
+                                   &target,
                                    aQuirks);
 
 #ifdef DEBUG
   if (!aPreventScriptExecution) {
     NS_ASSERTION(!aTargetNode->IsInDoc(),
                  "If script execution isn't prevented, "
                  "the target node must not be in doc.");
     nsCOMPtr<nsIDOMDocumentFragment> domFrag = do_QueryInterface(aTargetNode);
     NS_ASSERTION(domFrag,
       "If script execution isn't prevented, must parse to DOM fragment.");
   }
 #endif
 
   mTreeBuilder->SetPreventScriptExecution(aPreventScriptExecution);
 
-  return Tokenize(aSourceBuffer, doc, true);
+  Tokenize(aSourceBuffer, doc, true);
+  return NS_OK;
 }
 
 nsresult
 nsHtml5StringParser::ParseDocument(const nsAString& aSourceBuffer,
                                    nsIDocument* aTargetDoc,
                                    bool aScriptingEnabledForNoscriptParsing)
 {
   MOZ_ASSERT(!aTargetDoc->GetFirstChild());
@@ -75,50 +77,60 @@ nsHtml5StringParser::ParseDocument(const
 
   mTreeBuilder->setFragmentContext(nullptr,
                                    kNameSpaceID_None,
                                    nullptr,
                                    false);
 
   mTreeBuilder->SetPreventScriptExecution(true);
 
-  return Tokenize(aSourceBuffer, aTargetDoc, aScriptingEnabledForNoscriptParsing);
+  Tokenize(aSourceBuffer, aTargetDoc, aScriptingEnabledForNoscriptParsing);
+  return NS_OK;
 }
 
-nsresult
+void
 nsHtml5StringParser::Tokenize(const nsAString& aSourceBuffer,
                               nsIDocument* aDocument,
                               bool aScriptingEnabledForNoscriptParsing) {
 
   nsIURI* uri = aDocument->GetDocumentURI();
 
-  mBuilder->Init(aDocument, uri, nullptr, nullptr);
+  mExecutor->Init(aDocument, uri, nullptr, nullptr);
 
-  mBuilder->SetParser(this);
-  mBuilder->SetNodeInfoManager(aDocument->NodeInfoManager());
+  mExecutor->SetParser(this);
+  mExecutor->SetNodeInfoManager(aDocument->NodeInfoManager());
 
-  // Mark the parser as *not* broken by passing NS_OK
-  nsresult rv = mBuilder->MarkAsBroken(NS_OK);
-
+  NS_PRECONDITION(!mExecutor->HasStarted(),
+                  "Tried to start parse without initializing the parser.");
   mTreeBuilder->setScriptingEnabled(aScriptingEnabledForNoscriptParsing);
   mTreeBuilder->setIsSrcdocDocument(aDocument->IsSrcdocDocument()); 
-  mBuilder->Start();
   mTokenizer->start();
+  mExecutor->Start(); // Don't call WillBuildModel in fragment case
   if (!aSourceBuffer.IsEmpty()) {
     bool lastWasCR = false;
     nsHtml5DependentUTF16Buffer buffer(aSourceBuffer);
     while (buffer.hasMore()) {
       buffer.adjust(lastWasCR);
       lastWasCR = false;
       if (buffer.hasMore()) {
         lastWasCR = mTokenizer->tokenizeBuffer(&buffer);
-        if (NS_FAILED(rv = mBuilder->IsBroken())) {
-          break;
+        if (mTreeBuilder->HasScript()) {
+          // If we come here, we are in createContextualFragment() or in the
+          // upcoming document.parse(). It's unclear if it's really necessary
+          // to flush here, but let's do so for consistency with other flushes
+          // to avoid different code paths on the executor side.
+          mTreeBuilder->Flush(); // Move ops to the executor
+          mExecutor->FlushDocumentWrite(); // run the ops
         }
       }
     }
   }
   mTokenizer->eof();
+  mTreeBuilder->StreamEnded();
+  mTreeBuilder->Flush();
+  mExecutor->FlushDocumentWrite();
   mTokenizer->end();
-  mBuilder->Finish();
+  mExecutor->DropParserAndPerfHint();
+  mExecutor->DropHeldElements();
+  mTreeBuilder->DropHandles();
   mAtomTable.Clear();
-  return rv;
+  mExecutor->Reset();
 }
--- a/parser/html/nsHtml5StringParser.h
+++ b/parser/html/nsHtml5StringParser.h
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsHtml5StringParser_h
 #define nsHtml5StringParser_h
 
 #include "nsHtml5AtomTable.h"
 #include "nsParserBase.h"
 
-class nsHtml5OplessBuilder;
+class nsHtml5TreeOpExecutor;
 class nsHtml5TreeBuilder;
 class nsHtml5Tokenizer;
 class nsIContent;
 class nsIDocument;
 
 class nsHtml5StringParser : public nsParserBase
 {
   public:
@@ -53,24 +53,24 @@ class nsHtml5StringParser : public nsPar
      *
      */
     nsresult ParseDocument(const nsAString& aSourceBuffer,
                            nsIDocument* aTargetDoc,
                            bool aScriptingEnabledForNoscriptParsing);
 
   private:
 
-    nsresult Tokenize(const nsAString& aSourceBuffer,
-                      nsIDocument* aDocument,
-                      bool aScriptingEnabledForNoscriptParsing);
+    void Tokenize(const nsAString& aSourceBuffer,
+                  nsIDocument* aDocument,
+                  bool aScriptingEnabledForNoscriptParsing);
 
     /**
      * The tree operation executor
      */
-    nsRefPtr<nsHtml5OplessBuilder>      mBuilder;
+    nsRefPtr<nsHtml5TreeOpExecutor>     mExecutor;
 
     /**
      * The HTML5 tree builder
      */
     const nsAutoPtr<nsHtml5TreeBuilder> mTreeBuilder;
 
     /**
      * The HTML5 tokenizer
--- a/parser/html/nsHtml5Tokenizer.cpp
+++ b/parser/html/nsHtml5Tokenizer.cpp
@@ -29,17 +29,17 @@
  */
 
 #define nsHtml5Tokenizer_cpp__
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5DocumentMode.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsHtml5NamedCharacters.h"
 #include "nsHtml5NamedCharactersAccel.h"
 #include "nsHtml5Atoms.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Macros.h"
@@ -93,18 +93,17 @@ nsHtml5Tokenizer::nsHtml5Tokenizer(nsHtm
     encodingDeclarationHandler(nullptr),
     bmpChar(jArray<char16_t,int32_t>::newJArray(1)),
     astralChar(jArray<char16_t,int32_t>::newJArray(2)),
     tagName(nullptr),
     attributeName(nullptr),
     doctypeName(nullptr),
     publicIdentifier(nullptr),
     systemIdentifier(nullptr),
-    attributes(tokenHandler->HasBuilder() ? new nsHtml5HtmlAttributes(0) : nullptr),
-    newAttributesEachTime(!tokenHandler->HasBuilder()),
+    attributes(nullptr),
     viewingXmlSource(viewingXmlSource)
 {
   MOZ_COUNT_CTOR(nsHtml5Tokenizer);
 }
 
 void 
 nsHtml5Tokenizer::setInterner(nsHtml5AtomTable* interner)
 {
@@ -280,16 +279,22 @@ nsHtml5Tokenizer::flushChars(char16_t* b
 {
   if (pos > cstart) {
     tokenHandler->characters(buf, cstart, pos - cstart);
   }
   cstart = INT32_MAX;
 }
 
 void 
+nsHtml5Tokenizer::resetAttributes()
+{
+  attributes = nullptr;
+}
+
+void 
 nsHtml5Tokenizer::strBufToElementNameString()
 {
   tagName = nsHtml5ElementName::elementNameByBuffer(strBuf, 0, strBufLen, interner);
 }
 
 int32_t 
 nsHtml5Tokenizer::emitCurrentTagToken(bool selfClosing, int32_t pos)
 {
@@ -297,36 +302,27 @@ nsHtml5Tokenizer::emitCurrentTagToken(bo
   maybeErrSlashInEndTag(selfClosing);
   stateSave = NS_HTML5TOKENIZER_DATA;
   nsHtml5HtmlAttributes* attrs = (!attributes ? nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES : attributes);
   if (endTag) {
     maybeErrAttributesOnEndTag(attrs);
     if (!viewingXmlSource) {
       tokenHandler->endTag(tagName);
     }
-    if (newAttributesEachTime) {
-      delete attributes;
-      attributes = nullptr;
-    }
+    delete attributes;
   } else {
     if (viewingXmlSource) {
-      MOZ_ASSERT(newAttributesEachTime);
       delete attributes;
-      attributes = nullptr;
     } else {
       tokenHandler->startTag(tagName, attrs, selfClosing);
     }
   }
   tagName->release();
   tagName = nullptr;
-  if (newAttributesEachTime) {
-    attributes = nullptr;
-  } else {
-    attributes->clear(0);
-  }
+  resetAttributes();
   return stateSave;
 }
 
 void 
 nsHtml5Tokenizer::attributeNameComplete()
 {
   attributeName = nsHtml5AttributeName::nameByBuffer(strBuf, 0, strBufLen, interner);
   if (!attributes) {
@@ -3931,16 +3927,21 @@ nsHtml5Tokenizer::end()
     tagName->release();
     tagName = nullptr;
   }
   if (attributeName) {
     attributeName->release();
     attributeName = nullptr;
   }
   tokenHandler->endTokenization();
+  if (attributes) {
+    attributes->clear(0);
+    delete attributes;
+    attributes = nullptr;
+  }
 }
 
 void 
 nsHtml5Tokenizer::requestSuspension()
 {
   shouldSuspend = true;
 }
 
@@ -3975,21 +3976,19 @@ nsHtml5Tokenizer::resetToDataState()
   if (tagName) {
     tagName->release();
     tagName = nullptr;
   }
   if (attributeName) {
     attributeName->release();
     attributeName = nullptr;
   }
-  if (newAttributesEachTime) {
-    if (attributes) {
-      delete attributes;
-      attributes = nullptr;
-    }
+  if (attributes) {
+    delete attributes;
+    attributes = nullptr;
   }
 }
 
 void 
 nsHtml5Tokenizer::loadState(nsHtml5Tokenizer* other)
 {
   strBufLen = other->strBufLen;
   if (strBufLen > strBuf.length) {
@@ -4076,18 +4075,16 @@ nsHtml5Tokenizer::setEncodingDeclaration
 {
   this->encodingDeclarationHandler = encodingDeclarationHandler;
 }
 
 
 nsHtml5Tokenizer::~nsHtml5Tokenizer()
 {
   MOZ_COUNT_DTOR(nsHtml5Tokenizer);
-  delete attributes;
-  attributes = nullptr;
 }
 
 void
 nsHtml5Tokenizer::initializeStatics()
 {
 }
 
 void
--- a/parser/html/nsHtml5Tokenizer.h
+++ b/parser/html/nsHtml5Tokenizer.h
@@ -30,17 +30,17 @@
 
 #ifndef nsHtml5Tokenizer_h
 #define nsHtml5Tokenizer_h
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5DocumentMode.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsHtml5NamedCharacters.h"
 #include "nsHtml5NamedCharactersAccel.h"
 #include "nsHtml5Atoms.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Macros.h"
@@ -125,17 +125,16 @@ class nsHtml5Tokenizer
     nsHtml5ElementName* tagName;
   protected:
     nsHtml5AttributeName* attributeName;
   private:
     nsIAtom* doctypeName;
     nsString* publicIdentifier;
     nsString* systemIdentifier;
     nsHtml5HtmlAttributes* attributes;
-    bool newAttributesEachTime;
     bool shouldSuspend;
   protected:
     bool confident;
   private:
     int32_t line;
     nsHtml5AtomTable* interner;
     bool viewingXmlSource;
   public:
@@ -202,16 +201,17 @@ class nsHtml5Tokenizer
       appendLongStrBuf(strBuf, 0, strBufLen);
     }
 
     nsString* longStrBufToString();
     void emitComment(int32_t provisionalHyphens, int32_t pos);
   protected:
     void flushChars(char16_t* buf, int32_t pos);
   private:
+    void resetAttributes();
     void strBufToElementNameString();
     int32_t emitCurrentTagToken(bool selfClosing, int32_t pos);
     void attributeNameComplete();
     void addAttributeWithoutValue();
     void addAttributeWithValue();
   public:
     void start();
     bool tokenizeBuffer(nsHtml5UTF16Buffer* buffer);
--- a/parser/html/nsHtml5TokenizerHSupplement.h
+++ b/parser/html/nsHtml5TokenizerHSupplement.h
@@ -1,17 +1,12 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-inline nsHtml5HtmlAttributes* GetAttributes()
-{
-  return attributes;
-}
-
 nsAutoPtr<nsHtml5Highlighter> mViewSource;
 
 /**
  * Starts handling text/plain. This is a one-way initialization. There is
  * no corresponding EndPlainText() call.
  */
 void StartPlainText();
 
--- a/parser/html/nsHtml5TokenizerLoopPolicies.h
+++ b/parser/html/nsHtml5TokenizerLoopPolicies.h
@@ -10,38 +10,34 @@
  * when _not_ viewing source.
  */
 struct nsHtml5SilentPolicy
 {
   static const bool reportErrors = false;
   static int32_t transition(nsHtml5Highlighter* aHighlighter,
                             int32_t aState,
                             bool aReconsume,
-                            int32_t aPos)
-  {
+                            int32_t aPos) {
     return aState;
   }
-  static void completedNamedCharacterReference(nsHtml5Highlighter* aHighlighter)
-  {
+  static void completedNamedCharacterReference(nsHtml5Highlighter* aHighlighter) {
   }
 };
 
 /**
  * This policy reports the tokenizer transitions to a highlighter. To be used
  * when viewing source.
  */
 struct nsHtml5ViewSourcePolicy
 {
   static const bool reportErrors = true;
   static int32_t transition(nsHtml5Highlighter* aHighlighter,
                             int32_t aState,
                             bool aReconsume,
-                            int32_t aPos)
-  {
+                            int32_t aPos) {
     return aHighlighter->Transition(aState, aReconsume, aPos);
   }
-  static void completedNamedCharacterReference(nsHtml5Highlighter* aHighlighter)
-  {
+  static void completedNamedCharacterReference(nsHtml5Highlighter* aHighlighter) {
     aHighlighter->CompletedNamedCharacterReference();
   }
 };
 
 #endif // nsHtml5TokenizerLoopPolicies_h
--- a/parser/html/nsHtml5TreeBuilder.cpp
+++ b/parser/html/nsHtml5TreeBuilder.cpp
@@ -31,35 +31,33 @@
 #define nsHtml5TreeBuilder_cpp__
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsITimer.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5DocumentMode.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsHtml5Parser.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5TreeOperation.h"
 #include "nsHtml5PendingNotification.h"
 #include "nsHtml5StateSnapshot.h"
 #include "nsHtml5StackNode.h"
 #include "nsHtml5TreeOpExecutor.h"
 #include "nsHtml5StreamParser.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Highlighter.h"
 #include "nsHtml5PlainTextUtils.h"
 #include "nsHtml5ViewSourceUtils.h"
 #include "mozilla/Likely.h"
-#include "nsIContentHandle.h"
-#include "nsHtml5OplessBuilder.h"
 
 #include "nsHtml5Tokenizer.h"
 #include "nsHtml5MetaScanner.h"
 #include "nsHtml5AttributeName.h"
 #include "nsHtml5ElementName.h"
 #include "nsHtml5HtmlAttributes.h"
 #include "nsHtml5StackNode.h"
 #include "nsHtml5UTF16Buffer.h"
@@ -86,17 +84,17 @@ nsHtml5TreeBuilder::startTokenization(ns
   formPointer = nullptr;
   headPointer = nullptr;
   deepTreeSurrogateParent = nullptr;
   start(fragment);
   charBufferLen = 0;
   charBuffer = jArray<char16_t,int32_t>::newJArray(1024);
   framesetOk = true;
   if (fragment) {
-    nsIContentHandle* elt;
+    nsIContent** elt;
     if (contextNode) {
       elt = contextNode;
     } else {
       elt = createHtmlElementSetAsRoot(tokenizer->emptyAttributes());
     }
     nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HTML, elt);
     currentPtr++;
     stack[currentPtr] = node;
@@ -116,17 +114,17 @@ nsHtml5TreeBuilder::startTokenization(ns
     } else {
       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());
+      nsIContent** elt = createElement(kNameSpaceID_SVG, nsHtml5Atoms::svg, tokenizer->emptyAttributes());
       nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_SVG, nsHtml5Atoms::svg, elt);
       currentPtr++;
       stack[currentPtr] = node;
     }
   }
 }
 
 void 
@@ -1885,17 +1883,17 @@ nsHtml5TreeBuilder::startTag(nsHtml5Elem
         NS_HTML5_BREAK(starttagloop);
       }
     }
   }
   starttagloop_end: ;
   if (selfClosing) {
     errSelfClosing();
   }
-  if (!mBuilder && attributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
+  if (attributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
     delete attributes;
   }
 }
 
 void 
 nsHtml5TreeBuilder::startTagTitleInHead(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
@@ -3580,17 +3578,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));
+      nsIContent** clone = createElement(kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes(nullptr));
       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;
@@ -3601,17 +3599,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));
+    nsIContent** clone = createElement(kNameSpaceID_XHTML, formattingElt->name, formattingElt->attributes->cloneAttributes(nullptr));
     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);
@@ -3762,34 +3760,34 @@ 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));
+    nsIContent** clone = createElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr));
     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 
-nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle* child)
+nsHtml5TreeBuilder::insertIntoFosterParent(nsIContent** child)
 {
   int32_t tablePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE);
   int32_t templatePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TEMPLATE);
   if (templatePos >= tablePos) {
     appendElement(child, stack[templatePos]->node);
     return;
   }
   nsHtml5StackNode* node = stack[tablePos];
@@ -3841,31 +3839,31 @@ nsHtml5TreeBuilder::popOnEof()
   markMalformedIfScript(node->node);
   elementPopped(node->ns, node->popName, node->node);
   node->release();
 }
 
 void 
 nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush(nsHtml5HtmlAttributes* attributes)
 {
-  nsIContentHandle* elt = createHtmlElementSetAsRoot(attributes);
+  nsIContent** elt = createHtmlElementSetAsRoot(attributes);
   nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HTML, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush()
 {
   appendHtmlElementToDocumentAndPush(tokenizer->emptyAttributes());
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::head, attributes);
+  nsIContent** elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::head, attributes);
   appendElement(elt, stack[currentPtr]->node);
   headPointer = elt;
   nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HEAD, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(nsHtml5HtmlAttributes* attributes)
@@ -3877,17 +3875,17 @@ void
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement()
 {
   appendToCurrentNodeAndPushBodyElement(tokenizer->emptyAttributes());
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(nsHtml5HtmlAttributes* attributes)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes);
+  nsIContent** elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes);
   if (!isTemplateContents()) {
     formPointer = elt;
   }
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     insertIntoFosterParent(elt);
   } else {
@@ -3895,75 +3893,74 @@ nsHtml5TreeBuilder::appendToCurrentNodeA
   }
   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);
+  nsIContent** elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes);
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     insertIntoFosterParent(elt);
   } else {
     appendElement(elt, current->node);
   }
-  nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, clone);
+  nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, attributes->cloneAttributes(nullptr));
   push(node);
   append(node);
   node->retain();
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes);
+  nsIContent** elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes);
   appendElement(elt, stack[currentPtr]->node);
   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);
+  nsIContent** elt = createElement(kNameSpaceID_XHTML, popName, attributes);
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     insertIntoFosterParent(elt);
   } else {
     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);
+  nsIContent** elt = createElement(kNameSpaceID_MathML, popName, attributes);
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     insertIntoFosterParent(elt);
   } else {
     appendElement(elt, current->node);
   }
+  bool markAsHtmlIntegrationPoint = false;
+  if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName && annotationXmlEncodingPermitsHtml(attributes)) {
+    markAsHtmlIntegrationPoint = true;
+  }
   nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
   push(node);
 }
 
 bool 
 nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(nsHtml5HtmlAttributes* attributes)
 {
   nsString* encoding = attributes->getValue(nsHtml5AttributeName::ATTR_ENCODING);
@@ -3972,120 +3969,120 @@ 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);
+  nsIContent** elt = createElement(kNameSpaceID_SVG, popName, attributes);
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     insertIntoFosterParent(elt);
   } else {
     appendElement(elt, current->node);
   }
   nsHtml5StackNode* node = new nsHtml5StackNode(elementName, popName, elt);
   push(node);
 }
 
 void 
-nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
+nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContent** form)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, !form || fragment || isTemplateContents() ? nullptr : form);
+  nsIContent** elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, !form || fragment || isTemplateContents() ? nullptr : form);
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     insertIntoFosterParent(elt);
   } else {
     appendElement(elt, current->node);
   }
   nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt);
   push(node);
 }
 
 void 
-nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
+nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form);
+  nsIContent** elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form);
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     insertIntoFosterParent(elt);
   } else {
     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);
+  nsIContent** elt = createElement(kNameSpaceID_XHTML, popName, attributes);
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     insertIntoFosterParent(elt);
   } else {
     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);
+  nsIContent** elt = createElement(kNameSpaceID_SVG, popName, attributes);
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     insertIntoFosterParent(elt);
   } else {
     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);
+  nsIContent** elt = createElement(kNameSpaceID_MathML, popName, attributes);
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     insertIntoFosterParent(elt);
   } else {
     appendElement(elt, current->node);
   }
   elementPushed(kNameSpaceID_MathML, popName, elt);
   elementPopped(kNameSpaceID_MathML, popName, elt);
 }
 
 void 
-nsHtml5TreeBuilder::appendVoidElementToCurrent(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
+nsHtml5TreeBuilder::appendVoidElementToCurrent(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form);
+  nsIContent** elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form);
   nsHtml5StackNode* current = stack[currentPtr];
   appendElement(elt, current->node);
   elementPushed(kNameSpaceID_XHTML, name, elt);
   elementPopped(kNameSpaceID_XHTML, name, elt);
 }
 
 void 
 nsHtml5TreeBuilder::appendVoidFormToCurrent(nsHtml5HtmlAttributes* attributes)
 {
-  nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes);
+  nsIContent** elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes);
   formPointer = elt;
   nsHtml5StackNode* current = stack[currentPtr];
   appendElement(elt, current->node);
   elementPushed(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
   elementPopped(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
 }
 
 void 
@@ -4105,26 +4102,26 @@ nsHtml5TreeBuilder::isInForeignButNotHtm
 {
   if (currentPtr < 0) {
     return false;
   }
   return !isSpecialParentInForeign(stack[currentPtr]);
 }
 
 void 
-nsHtml5TreeBuilder::setFragmentContext(nsIAtom* context, int32_t ns, nsIContentHandle* node, bool quirks)
+nsHtml5TreeBuilder::setFragmentContext(nsIAtom* context, int32_t ns, nsIContent** node, bool quirks)
 {
   this->contextName = context;
   this->contextNamespace = ns;
   this->contextNode = node;
   this->fragment = (!!contextName);
   this->quirks = quirks;
 }
 
-nsIContentHandle* 
+nsIContent** 
 nsHtml5TreeBuilder::currentNode()
 {
   return stack[currentPtr]->node;
 }
 
 bool 
 nsHtml5TreeBuilder::isScriptingEnabled()
 {
@@ -4323,29 +4320,29 @@ nsHtml5TreeBuilder::findInArray(nsHtml5S
   for (int32_t i = listPtr; i >= 0; i--) {
     if (node == arr[i]) {
       return i;
     }
   }
   return -1;
 }
 
-nsIContentHandle* 
+nsIContent** 
 nsHtml5TreeBuilder::getFormPointer()
 {
   return formPointer;
 }
 
-nsIContentHandle* 
+nsIContent** 
 nsHtml5TreeBuilder::getHeadPointer()
 {
   return headPointer;
 }
 
-nsIContentHandle* 
+nsIContent** 
 nsHtml5TreeBuilder::getDeepTreeSurrogateParent()
 {
   return deepTreeSurrogateParent;
 }
 
 jArray<nsHtml5StackNode*,int32_t> 
 nsHtml5TreeBuilder::getListOfActiveFormattingElements()
 {
--- a/parser/html/nsHtml5TreeBuilder.h
+++ b/parser/html/nsHtml5TreeBuilder.h
@@ -32,35 +32,33 @@
 #define nsHtml5TreeBuilder_h
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsITimer.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5DocumentMode.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsHtml5Parser.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5TreeOperation.h"
 #include "nsHtml5PendingNotification.h"
 #include "nsHtml5StateSnapshot.h"
 #include "nsHtml5StackNode.h"
 #include "nsHtml5TreeOpExecutor.h"
 #include "nsHtml5StreamParser.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Highlighter.h"
 #include "nsHtml5PlainTextUtils.h"
 #include "nsHtml5ViewSourceUtils.h"
 #include "mozilla/Likely.h"
-#include "nsIContentHandle.h"
-#include "nsHtml5OplessBuilder.h"
 
 class nsHtml5StreamParser;
 
 class nsHtml5Tokenizer;
 class nsHtml5MetaScanner;
 class nsHtml5AttributeName;
 class nsHtml5ElementName;
 class nsHtml5HtmlAttributes;
@@ -80,26 +78,26 @@ class nsHtml5TreeBuilder : public nsAHtm
   protected:
     nsHtml5Tokenizer* tokenizer;
   private:
     bool scriptingEnabled;
     bool needToDropLF;
     bool fragment;
     nsIAtom* contextName;
     int32_t contextNamespace;
-    nsIContentHandle* contextNode;
+    nsIContent** contextNode;
     autoJArray<int32_t,int32_t> templateModeStack;
     int32_t templateModePtr;
     autoJArray<nsHtml5StackNode*,int32_t> stack;
     int32_t currentPtr;
     autoJArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements;
     int32_t listPtr;
-    nsIContentHandle* formPointer;
-    nsIContentHandle* headPointer;
-    nsIContentHandle* deepTreeSurrogateParent;
+    nsIContent** formPointer;
+    nsIContent** headPointer;
+    nsIContent** deepTreeSurrogateParent;
   protected:
     autoJArray<char16_t,int32_t> charBuffer;
     int32_t charBufferLen;
   private:
     bool quirks;
     bool isSrcdocDocument;
   public:
     void startTokenization(nsHtml5Tokenizer* self);
@@ -171,17 +169,17 @@ class nsHtml5TreeBuilder : public nsAHtm
     int32_t findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(nsIAtom* name);
     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);
+    void insertIntoFosterParent(nsIContent** child);
     bool isInStack(nsHtml5StackNode* node);
     void popTemplateMode();
     void pop();
     void silentPop();
     void popOnEof();
     void appendHtmlElementToDocumentAndPush(nsHtml5HtmlAttributes* attributes);
     void appendHtmlElementToDocumentAndPush();
     void appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes);
@@ -189,76 +187,76 @@ class nsHtml5TreeBuilder : public nsAHtm
     void appendToCurrentNodeAndPushBodyElement();
     void appendToCurrentNodeAndPushFormElementMayFoster(nsHtml5HtmlAttributes* attributes);
     void appendToCurrentNodeAndPushFormattingElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
     void appendToCurrentNodeAndPushElement(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
     void appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
     void appendToCurrentNodeAndPushElementMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
     bool annotationXmlEncodingPermitsHtml(nsHtml5HtmlAttributes* attributes);
     void appendToCurrentNodeAndPushElementMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
-    void appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form);
-    void appendVoidElementToCurrentMayFoster(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form);
+    void appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContent** form);
+    void appendVoidElementToCurrentMayFoster(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form);
     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 appendVoidElementToCurrent(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** 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* 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);
-    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);
+    nsIContent** createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes);
+    nsIContent** createElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form);
+    nsIContent** createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* attributes);
+    void detachFromParent(nsIContent** element);
+    bool hasChildren(nsIContent** element);
+    void appendElement(nsIContent** child, nsIContent** newParent);
+    void appendChildrenToNewParent(nsIContent** oldParent, nsIContent** newParent);
+    void insertFosterParentedChild(nsIContent** child, nsIContent** table, nsIContent** stackParent);
+    void insertFosterParentedCharacters(char16_t* buf, int32_t start, int32_t length, nsIContent** table, nsIContent** stackParent);
+    void appendCharacters(nsIContent** parent, char16_t* buf, int32_t start, int32_t length);
+    void appendIsindexPrompt(nsIContent** parent);
+    void appendComment(nsIContent** 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 addAttributesToElement(nsIContent** element, nsHtml5HtmlAttributes* attributes);
+    void markMalformedIfScript(nsIContent** elt);
     void start(bool fragmentMode);
     void end();
     void appendDoctypeToDocument(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier);
-    void elementPushed(int32_t ns, nsIAtom* name, nsIContentHandle* node);
-    void elementPopped(int32_t ns, nsIAtom* name, nsIContentHandle* node);
+    void elementPushed(int32_t ns, nsIAtom* name, nsIContent** node);
+    void elementPopped(int32_t ns, nsIAtom* name, nsIContent** node);
   public:
     inline bool cdataSectionAllowed()
     {
       return isInForeign();
     }
 
   private:
     bool isInForeign();
     bool isInForeignButNotHtmlOrMathTextIntegrationPoint();
   public:
-    void setFragmentContext(nsIAtom* context, int32_t ns, nsIContentHandle* node, bool quirks);
+    void setFragmentContext(nsIAtom* context, int32_t ns, nsIContent** node, bool quirks);
   protected:
-    nsIContentHandle* currentNode();
+    nsIContent** currentNode();
   public:
     bool isScriptingEnabled();
     void setScriptingEnabled(bool scriptingEnabled);
     void setIsSrcdocDocument(bool isSrcdocDocument);
     void flushCharacters();
   private:
     bool charBufferContainsNonWhitespace();
   public:
     nsAHtml5TreeBuilderState* newSnapshot();
     bool snapshotMatches(nsAHtml5TreeBuilderState* snapshot);
     void loadState(nsAHtml5TreeBuilderState* snapshot, nsHtml5AtomTable* interner);
   private:
     int32_t findInArray(nsHtml5StackNode* node, jArray<nsHtml5StackNode*,int32_t> arr);
   public:
-    nsIContentHandle* getFormPointer();
-    nsIContentHandle* getHeadPointer();
-    nsIContentHandle* getDeepTreeSurrogateParent();
+    nsIContent** getFormPointer();
+    nsIContent** getHeadPointer();
+    nsIContent** getDeepTreeSurrogateParent();
     jArray<nsHtml5StackNode*,int32_t> getListOfActiveFormattingElements();
     jArray<nsHtml5StackNode*,int32_t> getStack();
     jArray<int32_t,int32_t> getTemplateModeStack();
     int32_t getMode();
     int32_t getOriginalMode();
     bool isFramesetOk();
     bool isNeedToDropLF();
     bool isQuirks();
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -8,45 +8,23 @@
 #include "nsIPresShell.h"
 #include "nsEventDispatcher.h"
 #include "nsNodeUtils.h"
 #include "nsIFrame.h"
 #include "mozilla/Likely.h"
 
 class nsPresContext;
 
-nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder)
-  : scriptingEnabled(false)
-  , fragment(false)
-  , contextNode(nullptr)
-  , formPointer(nullptr)
-  , headPointer(nullptr)
-  , mBuilder(aBuilder)
-  , mViewSource(nullptr)
-  , mOpSink(nullptr)
-  , mHandles(nullptr)
-  , mHandlesUsed(0)
-  , mSpeculativeLoadStage(nullptr)
-  , mCurrentHtmlScriptIsAsyncOrDefer(false)
-  , mPreventScriptExecution(false)
-#ifdef DEBUG
-  , mActive(false)
-#endif
-{
-  MOZ_COUNT_CTOR(nsHtml5TreeBuilder);
-}
-
 nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink,
                                        nsHtml5TreeOpStage* aStage)
   : scriptingEnabled(false)
   , fragment(false)
   , contextNode(nullptr)
   , formPointer(nullptr)
   , headPointer(nullptr)
-  , mBuilder(nullptr)
   , mViewSource(nullptr)
   , mOpSink(aOpSink)
   , mHandles(new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH])
   , mHandlesUsed(0)
   , mSpeculativeLoadStage(aStage)
   , mCurrentHtmlScriptIsAsyncOrDefer(false)
   , mPreventScriptExecution(false)
 #ifdef DEBUG
@@ -58,42 +36,27 @@ nsHtml5TreeBuilder::nsHtml5TreeBuilder(n
 
 nsHtml5TreeBuilder::~nsHtml5TreeBuilder()
 {
   MOZ_COUNT_DTOR(nsHtml5TreeBuilder);
   NS_ASSERTION(!mActive, "nsHtml5TreeBuilder deleted without ever calling end() on it!");
   mOpQueue.Clear();
 }
 
-nsIContentHandle*
+nsIContent**
 nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes)
 {
   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* elem =
-      nsHtml5TreeOperation::CreateElement(aNamespace,
-                                          name,
-                                          aAttributes,
-                                          mozilla::dom::FROM_PARSER_FRAGMENT,
-                                          mBuilder);
-    if (MOZ_UNLIKELY(aAttributes != tokenizer->GetAttributes() &&
-                     aAttributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES)) {
-      delete aAttributes;
-    }
-    return elem;
-  }
-
-  nsIContentHandle* content = AllocateContentHandle();
+  nsIContent** content = AllocateContentHandle();
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(aNamespace,
                aName,
                aAttributes,
                content,
                !!mSpeculativeLoadStage);
   // mSpeculativeLoadStage is non-null only in the off-the-main-thread
@@ -241,310 +204,173 @@ nsHtml5TreeBuilder::createElement(int32_
     }
   }
 
   // End wall of code for speculative loading
   
   return content;
 }
 
-nsIContentHandle*
-nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes, nsIContentHandle* aFormElement)
+nsIContent**
+nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes, nsIContent** aFormElement)
 {
-  nsIContentHandle* content = createElement(aNamespace, aName, aAttributes);
+  nsIContent** content = createElement(aNamespace, aName, aAttributes);
   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);
-    }
+    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+    NS_ASSERTION(treeOp, "Tree op allocation failed.");
+    treeOp->Init(eTreeOpSetFormElement, content, aFormElement);
   }
   return content;
 }
 
-nsIContentHandle*
+nsIContent**
 nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* aAttributes)
 {
-  nsIContentHandle* content = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::html, aAttributes);
-  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);
-  }
+  nsIContent** content = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::html, aAttributes);
+  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+  NS_ASSERTION(treeOp, "Tree op allocation failed.");
+  treeOp->Init(eTreeOpAppendToDocument, content);
   return content;
 }
 
 void
-nsHtml5TreeBuilder::detachFromParent(nsIContentHandle* aElement)
+nsHtml5TreeBuilder::detachFromParent(nsIContent** aElement)
 {
   NS_PRECONDITION(aElement, "Null element");
 
-  if (mBuilder) {
-    nsHtml5TreeOperation::Detach(static_cast<nsIContent*>(aElement),
-                                 mBuilder);
-    return;
-  }
-
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(eTreeOpDetach, aElement);
 }
 
 void
-nsHtml5TreeBuilder::appendElement(nsIContentHandle* aChild, nsIContentHandle* aParent)
+nsHtml5TreeBuilder::appendElement(nsIContent** aChild, nsIContent** aParent)
 {
   NS_PRECONDITION(aChild, "Null child");
   NS_PRECONDITION(aParent, "Null parent");
   if (deepTreeSurrogateParent) {
     return;
   }
-
-  if (mBuilder) {
-    nsresult rv = nsHtml5TreeOperation::Append(static_cast<nsIContent*>(aChild),
-                                               static_cast<nsIContent*>(aParent),
-                                               mBuilder);
-    if (NS_FAILED(rv)) {
-      MarkAsBrokenAndRequestSuspension(rv);
-    }
-    return;
-  }
-
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(eTreeOpAppend, aChild, aParent);
 }
 
 void
-nsHtml5TreeBuilder::appendChildrenToNewParent(nsIContentHandle* aOldParent, nsIContentHandle* aNewParent)
+nsHtml5TreeBuilder::appendChildrenToNewParent(nsIContent** aOldParent, nsIContent** aNewParent)
 {
   NS_PRECONDITION(aOldParent, "Null old parent");
   NS_PRECONDITION(aNewParent, "Null new parent");
 
-  if (mBuilder) {
-    nsresult rv = nsHtml5TreeOperation::AppendChildrenToNewParent(
-      static_cast<nsIContent*>(aOldParent),
-      static_cast<nsIContent*>(aNewParent),
-      mBuilder);
-    if (NS_FAILED(rv)) {
-      MarkAsBrokenAndRequestSuspension(rv);
-    }
-    return;
-  }
-
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(eTreeOpAppendChildrenToNewParent, aOldParent, aNewParent);
 }
 
 void
-nsHtml5TreeBuilder::insertFosterParentedCharacters(char16_t* aBuffer, int32_t aStart, int32_t aLength, nsIContentHandle* aTable, nsIContentHandle* aStackParent)
+nsHtml5TreeBuilder::insertFosterParentedCharacters(char16_t* aBuffer, int32_t aStart, int32_t aLength, nsIContent** aTable, nsIContent** aStackParent)
 {
   NS_PRECONDITION(aBuffer, "Null buffer");
   NS_PRECONDITION(aTable, "Null table");
   NS_PRECONDITION(aStackParent, "Null stack parent");
-  MOZ_ASSERT(!aStart, "aStart must always be zero.");
-
-  if (mBuilder) {
-    nsresult rv = nsHtml5TreeOperation::FosterParentText(
-      static_cast<nsIContent*>(aStackParent),
-      aBuffer, // XXX aStart always ignored???
-      aLength,
-      static_cast<nsIContent*>(aTable),
-      mBuilder);
-    if (NS_FAILED(rv)) {
-      MarkAsBrokenAndRequestSuspension(rv);
-    }
-    return;
-  }
 
   char16_t* bufferCopy = new char16_t[aLength];
   memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
   
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(eTreeOpFosterParentText, bufferCopy, aLength, aStackParent, aTable);
 }
 
 void
-nsHtml5TreeBuilder::insertFosterParentedChild(nsIContentHandle* aChild, nsIContentHandle* aTable, nsIContentHandle* aStackParent)
+nsHtml5TreeBuilder::insertFosterParentedChild(nsIContent** aChild, nsIContent** aTable, nsIContent** aStackParent)
 {
   NS_PRECONDITION(aChild, "Null child");
   NS_PRECONDITION(aTable, "Null table");
   NS_PRECONDITION(aStackParent, "Null stack parent");
 
-  if (mBuilder) {
-    nsresult rv = nsHtml5TreeOperation::FosterParent(
-      static_cast<nsIContent*>(aChild),
-      static_cast<nsIContent*>(aStackParent),
-      static_cast<nsIContent*>(aTable),
-      mBuilder);
-    if (NS_FAILED(rv)) {
-      MarkAsBrokenAndRequestSuspension(rv);
-    }
-    return;
-  }
-
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(eTreeOpFosterParent, aChild, aStackParent, aTable);
 }
 
 void
-nsHtml5TreeBuilder::appendCharacters(nsIContentHandle* aParent, char16_t* aBuffer, int32_t aStart, int32_t aLength)
+nsHtml5TreeBuilder::appendCharacters(nsIContent** aParent, char16_t* aBuffer, int32_t aStart, int32_t aLength)
 {
   NS_PRECONDITION(aBuffer, "Null buffer");
   NS_PRECONDITION(aParent, "Null parent");
-  MOZ_ASSERT(!aStart, "aStart must always be zero.");
-
-  if (mBuilder) {
-    nsresult rv = nsHtml5TreeOperation::AppendText(
-      aBuffer, // XXX aStart always ignored???
-      aLength,
-      static_cast<nsIContent*>(deepTreeSurrogateParent ?
-                               deepTreeSurrogateParent : aParent),
-      mBuilder);
-    if (NS_FAILED(rv)) {
-      MarkAsBrokenAndRequestSuspension(rv);
-    }
-    return;
-  }
 
   char16_t* bufferCopy = new char16_t[aLength];
   memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
   
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(eTreeOpAppendText, bufferCopy, aLength,
       deepTreeSurrogateParent ? deepTreeSurrogateParent : aParent);
 }
 
 void
-nsHtml5TreeBuilder::appendIsindexPrompt(nsIContentHandle* aParent)
+nsHtml5TreeBuilder::appendIsindexPrompt(nsIContent** aParent)
 {
   NS_PRECONDITION(aParent, "Null parent");
 
-  if (mBuilder) {
-    nsresult rv = nsHtml5TreeOperation::AppendIsindexPrompt(
-      static_cast<nsIContent*>(aParent),
-      mBuilder);
-    if (NS_FAILED(rv)) {
-      MarkAsBrokenAndRequestSuspension(rv);
-    }
-    return;
-  }
-
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(eTreeOpAppendIsindexPrompt, aParent);
 }
 
 void
-nsHtml5TreeBuilder::appendComment(nsIContentHandle* aParent, char16_t* aBuffer, int32_t aStart, int32_t aLength)
+nsHtml5TreeBuilder::appendComment(nsIContent** aParent, char16_t* aBuffer, int32_t aStart, int32_t aLength)
 {
   NS_PRECONDITION(aBuffer, "Null buffer");
   NS_PRECONDITION(aParent, "Null parent");
-  MOZ_ASSERT(!aStart, "aStart must always be zero.");
-
   if (deepTreeSurrogateParent) {
     return;
   }
 
-  if (mBuilder) {
-    nsresult rv = nsHtml5TreeOperation::AppendComment(
-      static_cast<nsIContent*>(aParent),
-      aBuffer, // XXX aStart always ignored???
-      aLength,
-      mBuilder);
-    if (NS_FAILED(rv)) {
-      MarkAsBrokenAndRequestSuspension(rv);
-    }
-    return;
-  }
-
   char16_t* bufferCopy = new char16_t[aLength];
   memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
   
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(eTreeOpAppendComment, bufferCopy, aLength, aParent);
 }
 
 void
 nsHtml5TreeBuilder::appendCommentToDocument(char16_t* aBuffer, int32_t aStart, int32_t aLength)
 {
   NS_PRECONDITION(aBuffer, "Null buffer");
-  MOZ_ASSERT(!aStart, "aStart must always be zero.");
-
-  if (mBuilder) {
-    nsresult rv = nsHtml5TreeOperation::AppendCommentToDocument(
-      aBuffer, // XXX aStart always ignored???
-      aLength,
-      mBuilder);
-    if (NS_FAILED(rv)) {
-      MarkAsBrokenAndRequestSuspension(rv);
-    }
-    return;
-  }
 
   char16_t* bufferCopy = new char16_t[aLength];
   memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
   
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(eTreeOpAppendCommentToDocument, bufferCopy, aLength);
 }
 
 void
-nsHtml5TreeBuilder::addAttributesToElement(nsIContentHandle* aElement, nsHtml5HtmlAttributes* aAttributes)
+nsHtml5TreeBuilder::addAttributesToElement(nsIContent** aElement, nsHtml5HtmlAttributes* aAttributes)
 {
   NS_PRECONDITION(aElement, "Null element");
   NS_PRECONDITION(aAttributes, "Null attributes");
 
   if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
     return;
   }
-
-  if (mBuilder) {
-    MOZ_ASSERT(aAttributes == tokenizer->GetAttributes(),
-      "Using attribute other than the tokenizer's to add to body or html.");
-    nsresult rv = nsHtml5TreeOperation::AddAttributes(
-      static_cast<nsIContent*>(aElement),
-      aAttributes,
-      mBuilder);
-    if (NS_FAILED(rv)) {
-      MarkAsBrokenAndRequestSuspension(rv);
-    }
-    return;
-  }
-
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(aElement, aAttributes);
 }
 
 void
-nsHtml5TreeBuilder::markMalformedIfScript(nsIContentHandle* aElement)
+nsHtml5TreeBuilder::markMalformedIfScript(nsIContent** aElement)
 {
   NS_PRECONDITION(aElement, "Null element");
 
-  if (mBuilder) {
-    nsHtml5TreeOperation::MarkMalformedIfScript(
-      static_cast<nsIContent*>(aElement));
-    return;
-  }
-
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(eTreeOpMarkMalformedIfScript, aElement);
 }
 
 void
 nsHtml5TreeBuilder::start(bool fragment)
 {
@@ -564,38 +390,25 @@ nsHtml5TreeBuilder::end()
 #endif
 }
 
 void
 nsHtml5TreeBuilder::appendDoctypeToDocument(nsIAtom* aName, nsString* aPublicId, nsString* aSystemId)
 {
   NS_PRECONDITION(aName, "Null name");
 
-  if (mBuilder) {
-    nsCOMPtr<nsIAtom> name = nsHtml5TreeOperation::Reget(aName);
-    nsresult rv =
-      nsHtml5TreeOperation::AppendDoctypeToDocument(name,
-                                                    *aPublicId,
-                                                    *aSystemId,
-                                                    mBuilder);
-    if (NS_FAILED(rv)) {
-      MarkAsBrokenAndRequestSuspension(rv);
-    }
-    return;
-  }
-
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(aName, *aPublicId, *aSystemId);
   // nsXMLContentSink can flush here, but what's the point?
   // It can also interrupt here, but we can't.
 }
 
 void
-nsHtml5TreeBuilder::elementPushed(int32_t aNamespace, nsIAtom* aName, nsIContentHandle* aElement)
+nsHtml5TreeBuilder::elementPushed(int32_t aNamespace, nsIAtom* aName, nsIContent** aElement)
 {
   NS_ASSERTION(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG || aNamespace == kNameSpaceID_MathML, "Element isn't HTML, SVG or MathML!");
   NS_ASSERTION(aName, "Element doesn't have local name!");
   NS_ASSERTION(aElement, "No element!");
   /*
    * The frame constructor uses recursive algorithms, so it can't deal with
    * arbitrarily deep trees. This is especially a problem on Windows where
    * the permitted depth of the runtime stack is rather small.
@@ -624,170 +437,120 @@ nsHtml5TreeBuilder::elementPushed(int32_
         aName == nsHtml5Atoms::colgroup ||
         aName == nsHtml5Atoms::style)) {
     deepTreeSurrogateParent = aElement;
   }
   if (aNamespace != kNameSpaceID_XHTML) {
     return;
   }
   if (aName == nsHtml5Atoms::body || aName == nsHtml5Atoms::frameset) {
-    if (mBuilder) {
-      // InnerHTML and DOMParser shouldn't start layout anyway
-      return;
-    }
     nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     NS_ASSERTION(treeOp, "Tree op allocation failed.");
     treeOp->Init(eTreeOpStartLayout);
     return;
   }
   if (aName == nsHtml5Atoms::input ||
       aName == nsHtml5Atoms::button) {
     if (!formPointer) {
       // If form inputs don't belong to a form, their state preservation
       // won't work right without an append notification flush at this
       // point. See bug 497861.
-      if (mBuilder) {
-        mBuilder->FlushPendingAppendNotifications();
-      } else {
-        mOpQueue.AppendElement()->Init(eTreeOpFlushPendingAppendNotifications);
-      }
+      mOpQueue.AppendElement()->Init(eTreeOpFlushPendingAppendNotifications);
     }
-    if (mBuilder) {
-      nsHtml5TreeOperation::DoneCreatingElement(static_cast<nsIContent*>(aElement));
-    } else {
-      mOpQueue.AppendElement()->Init(eTreeOpDoneCreatingElement, aElement);
-    }
+    mOpQueue.AppendElement()->Init(eTreeOpDoneCreatingElement, aElement);
     return;
   }
   if (aName == nsHtml5Atoms::audio ||
       aName == nsHtml5Atoms::video ||
       aName == nsHtml5Atoms::menuitem) {
-    if (mBuilder) {
-      nsHtml5TreeOperation::DoneCreatingElement(static_cast<nsIContent*>(aElement));
-    } else {
-      mOpQueue.AppendElement()->Init(eTreeOpDoneCreatingElement, aElement);
-    }
+    mOpQueue.AppendElement()->Init(eTreeOpDoneCreatingElement, aElement);
     return;
   }
 }
 
 void
-nsHtml5TreeBuilder::elementPopped(int32_t aNamespace, nsIAtom* aName, nsIContentHandle* aElement)
+nsHtml5TreeBuilder::elementPopped(int32_t aNamespace, nsIAtom* aName, nsIContent** aElement)
 {
   NS_ASSERTION(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG || aNamespace == kNameSpaceID_MathML, "Element isn't HTML, SVG or MathML!");
   NS_ASSERTION(aName, "Element doesn't have local name!");
   NS_ASSERTION(aElement, "No element!");
   if (deepTreeSurrogateParent && currentPtr <= MAX_REFLOW_DEPTH) {
     deepTreeSurrogateParent = nullptr;
   }
   if (aNamespace == kNameSpaceID_MathML) {
     return;
   }
   // we now have only SVG and HTML
   if (aName == nsHtml5Atoms::script) {
     if (mPreventScriptExecution) {
-      if (mBuilder) {
-        nsHtml5TreeOperation::PreventScriptExecution(static_cast<nsIContent*>(aElement));
-        return;
-      }
       mOpQueue.AppendElement()->Init(eTreeOpPreventScriptExecution, aElement);
       return;
     }
-    if (mBuilder) {
-      return;
-    }
     if (mCurrentHtmlScriptIsAsyncOrDefer) {
       NS_ASSERTION(aNamespace == kNameSpaceID_XHTML, 
                    "Only HTML scripts may be async/defer.");
       nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
       NS_ASSERTION(treeOp, "Tree op allocation failed.");
       treeOp->Init(eTreeOpRunScriptAsyncDefer, aElement);      
       mCurrentHtmlScriptIsAsyncOrDefer = false;
       return;
     }
     requestSuspension();
     nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     NS_ASSERTION(treeOp, "Tree op allocation failed.");
     treeOp->InitScript(aElement);
     return;
   }
   if (aName == nsHtml5Atoms::title) {
-    if (mBuilder) {
-      nsHtml5TreeOperation::DoneAddingChildren(static_cast<nsIContent*>(aElement), mBuilder);
-      return;
-    }
     nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     NS_ASSERTION(treeOp, "Tree op allocation failed.");
     treeOp->Init(eTreeOpDoneAddingChildren, aElement);
     return;
   }
   if (aName == nsHtml5Atoms::style || (aNamespace == kNameSpaceID_XHTML && aName == nsHtml5Atoms::link)) {
-    if (mBuilder) {
-      MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
-        "Scripts must be blocked.");
-      mBuilder->FlushPendingAppendNotifications();
-      mBuilder->UpdateStyleSheet(static_cast<nsIContent*>(aElement));
-      return;
-    }
     nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     NS_ASSERTION(treeOp, "Tree op allocation failed.");
     treeOp->Init(eTreeOpUpdateStyleSheet, aElement);
     return;
   }
   if (aNamespace == kNameSpaceID_SVG) {
     if (aName == nsHtml5Atoms::svg) {
-      if (mBuilder) {
-        nsHtml5TreeOperation::SvgLoad(static_cast<nsIContent*>(aElement));
-        return;
-      }
       nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
       NS_ASSERTION(treeOp, "Tree op allocation failed.");
       treeOp->Init(eTreeOpSvgLoad, aElement);
     }
     return;
   }
   // we now have only HTML
   // Some HTML nodes need DoneAddingChildren() called to initialize
   // properly (e.g. form state restoration).
   // XXX expose ElementName group here and do switch
   if (aName == nsHtml5Atoms::object ||
       aName == nsHtml5Atoms::applet) {
-    if (mBuilder) {
-      nsHtml5TreeOperation::DoneAddingChildren(static_cast<nsIContent*>(aElement), mBuilder);
-      return;
-    }
     nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     NS_ASSERTION(treeOp, "Tree op allocation failed.");
     treeOp->Init(eTreeOpDoneAddingChildren, aElement);
     return;
   }
   if (aName == nsHtml5Atoms::select || 
       aName == nsHtml5Atoms::textarea) {
     if (!formPointer) {
       // If form inputs don't belong to a form, their state preservation
       // won't work right without an append notification flush at this 
       // point. See bug 497861 and bug 539895.
-      if (mBuilder) {
-        mBuilder->FlushPendingAppendNotifications();
-      } else {
-        nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
-        NS_ASSERTION(treeOp, "Tree op allocation failed.");
-        treeOp->Init(eTreeOpFlushPendingAppendNotifications);
-      }
-    }
-    if (mBuilder) {
-      nsHtml5TreeOperation::DoneAddingChildren(static_cast<nsIContent*>(aElement), mBuilder);
-      return;
+      nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+      NS_ASSERTION(treeOp, "Tree op allocation failed.");
+      treeOp->Init(eTreeOpFlushPendingAppendNotifications);
     }
     nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     NS_ASSERTION(treeOp, "Tree op allocation failed.");
     treeOp->Init(eTreeOpDoneAddingChildren, aElement);
     return;
   }
-  if (aName == nsHtml5Atoms::meta && !fragment && !mBuilder) {
+  if (aName == nsHtml5Atoms::meta && !fragment) {
     nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
     NS_ASSERTION(treeOp, "Tree op allocation failed.");
     treeOp->Init(eTreeOpProcessMeta, aElement);
     return;
   }
   return;
 }
 
@@ -800,23 +563,19 @@ nsHtml5TreeBuilder::accumulateCharacters
     jArray<char16_t,int32_t> newBuf = jArray<char16_t,int32_t>::newJArray(newAllocLength);
     memcpy(newBuf, charBuffer, sizeof(char16_t) * charBufferLen);
     charBuffer = newBuf;
   }
   memcpy(charBuffer + charBufferLen, aBuf + aStart, sizeof(char16_t) * aLength);
   charBufferLen = newFillLen;
 }
 
-nsIContentHandle*
+nsIContent**
 nsHtml5TreeBuilder::AllocateContentHandle()
 {
-  if (MOZ_UNLIKELY(mBuilder)) {
-    MOZ_ASSUME_UNREACHABLE("Must never allocate a handle with builder.");
-    return nullptr;
-  }
   if (mHandlesUsed == NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH) {
     mOldHandles.AppendElement(mHandles.forget());
     mHandles = new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH];
     mHandlesUsed = 0;
   }
 #ifdef DEBUG
   mHandles[mHandlesUsed] = (nsIContent*)0xC0DEDBAD;
 #endif
@@ -831,20 +590,16 @@ nsHtml5TreeBuilder::HasScript()
     return false;
   }
   return mOpQueue.ElementAt(len - 1).IsRunScript();
 }
 
 bool
 nsHtml5TreeBuilder::Flush(bool aDiscretionary)
 {
-  if (MOZ_UNLIKELY(mBuilder)) {
-    MOZ_ASSUME_UNREACHABLE("Must never flush with builder.");
-    return false;
-  }
   if (!aDiscretionary ||
       !(charBufferLen &&
         currentPtr >= 0 &&
         stack[currentPtr]->isFosterParenting())) {
     // Don't flush text on discretionary flushes if the current element on
     // the stack is a foster-parenting element and there's pending text,
     // because flushing in that case would make the tree shape dependent on
     // where the flush points fall.
@@ -861,114 +616,95 @@ nsHtml5TreeBuilder::Flush(bool aDiscreti
   // no op sink: throw away ops
   mOpQueue.Clear();
   return false;
 }
 
 void
 nsHtml5TreeBuilder::FlushLoads()
 {
-  if (MOZ_UNLIKELY(mBuilder)) {
-    MOZ_ASSUME_UNREACHABLE("Must never flush loads with builder.");
-    return;
-  }
   if (!mSpeculativeLoadQueue.IsEmpty()) {
     mSpeculativeLoadStage->MoveSpeculativeLoadsFrom(mSpeculativeLoadQueue);
   }
 }
 
 void
 nsHtml5TreeBuilder::SetDocumentCharset(nsACString& aCharset, 
                                        int32_t aCharsetSource)
 {
-  if (mBuilder) {
-    mBuilder->SetDocumentCharsetAndSource(aCharset, aCharsetSource);
-  } else if (mSpeculativeLoadStage) {
+  if (mSpeculativeLoadStage) {
     mSpeculativeLoadQueue.AppendElement()->InitSetDocumentCharset(
       aCharset, aCharsetSource);
   } else {
     mOpQueue.AppendElement()->Init(
       eTreeOpSetDocumentCharset, aCharset, aCharsetSource);
   }
 }
 
 void
 nsHtml5TreeBuilder::StreamEnded()
 {
-  MOZ_ASSERT(!mBuilder, "Must not call StreamEnded with builder.");
-  MOZ_ASSERT(!fragment, "Must not parse fragments off the main thread.");
-  nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
-  NS_ASSERTION(treeOp, "Tree op allocation failed.");
-  treeOp->Init(eTreeOpStreamEnded);
+  // The fragment mode calls DidBuildModel from nsHtml5Parser. 
+  // Letting DidBuildModel be called from the executor in the fragment case
+  // confuses the EndLoad logic of nsHTMLDocument, since nsHTMLDocument
+  // thinks it is dealing with document.written content as opposed to 
+  // innerHTML content.
+  if (!fragment) {
+    nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+    NS_ASSERTION(treeOp, "Tree op allocation failed.");
+    treeOp->Init(eTreeOpStreamEnded);
+  }
 }
 
 void
 nsHtml5TreeBuilder::NeedsCharsetSwitchTo(const nsACString& aCharset,
                                          int32_t aCharsetSource,
                                          int32_t aLineNumber)
 {
-  if (MOZ_UNLIKELY(mBuilder)) {
-    MOZ_ASSUME_UNREACHABLE("Must never switch charset with builder.");
-    return;
-  }
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(eTreeOpNeedsCharsetSwitchTo,
                aCharset,
                aCharsetSource,
                aLineNumber);
 }
 
 void
 nsHtml5TreeBuilder::MaybeComplainAboutCharset(const char* aMsgId,
                                               bool aError,
                                               int32_t aLineNumber)
 {
-  if (MOZ_UNLIKELY(mBuilder)) {
-    MOZ_ASSUME_UNREACHABLE("Must never complain about charset with builder.");
-    return;
-  }
   mOpQueue.AppendElement()->Init(aMsgId, aError, aLineNumber);
 }
 
 void
 nsHtml5TreeBuilder::AddSnapshotToScript(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine)
 {
-  if (MOZ_UNLIKELY(mBuilder)) {
-    MOZ_ASSUME_UNREACHABLE("Must never use snapshots with builder.");
-    return;
-  }
   NS_PRECONDITION(HasScript(), "No script to add a snapshot to!");
   NS_PRECONDITION(aSnapshot, "Got null snapshot.");
   mOpQueue.ElementAt(mOpQueue.Length() - 1).SetSnapshot(aSnapshot, aLine);
 }
 
 void
 nsHtml5TreeBuilder::DropHandles()
 {
-  MOZ_ASSERT(!mBuilder, "Must not drop handles with builder.");
   mOldHandles.Clear();
   mHandlesUsed = 0;
 }
 
 void
 nsHtml5TreeBuilder::MarkAsBroken()
 {
-  if (MOZ_UNLIKELY(mBuilder)) {
-    MOZ_ASSUME_UNREACHABLE("Must not call this with builder.");
-    return;
-  }
   mOpQueue.Clear(); // Previous ops don't matter anymore
   mOpQueue.AppendElement()->Init(eTreeOpMarkAsBroken);
 }
 
 void
 nsHtml5TreeBuilder::StartPlainTextViewSource(const nsAutoString& aTitle)
 {
-  MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
   startTag(nsHtml5ElementName::ELT_TITLE,
            nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES,
            false);
 
   // XUL will add the "Source of: " prefix.
   uint32_t length = aTitle.Length();
   if (length > INT32_MAX) {
     length = INT32_MAX;
@@ -985,73 +721,63 @@ nsHtml5TreeBuilder::StartPlainTextViewSo
            false);
 
   StartPlainTextBody();
 }
 
 void
 nsHtml5TreeBuilder::StartPlainText()
 {
-  MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
   startTag(nsHtml5ElementName::ELT_LINK,
            nsHtml5PlainTextUtils::NewLinkAttributes(),
            false);
 
   StartPlainTextBody();
 }
 
 void
 nsHtml5TreeBuilder::StartPlainTextBody()
 {
-  MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
   startTag(nsHtml5ElementName::ELT_PRE,
            nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES,
            false);
   needToDropLF = false;
 }
 
 // DocumentModeHandler
 void
 nsHtml5TreeBuilder::documentMode(nsHtml5DocumentMode m)
 {
-  if (mBuilder) {
-    mBuilder->SetDocumentMode(m);
-    return;
-  }
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
   treeOp->Init(m);
 }
 
-nsIContentHandle*
-nsHtml5TreeBuilder::getDocumentFragmentForTemplate(nsIContentHandle* aTemplate)
+nsIContent**
+nsHtml5TreeBuilder::getDocumentFragmentForTemplate(nsIContent** aTemplate)
 {
-  if (mBuilder) {
-    return nsHtml5TreeOperation::GetDocumentFragmentForTemplate(static_cast<nsIContent*>(aTemplate));
-  }
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
   NS_ASSERTION(treeOp, "Tree op allocation failed.");
-  nsIContentHandle* fragHandle = AllocateContentHandle();
+  nsIContent** fragHandle = AllocateContentHandle();
   treeOp->Init(eTreeOpGetDocumentFragmentForTemplate, aTemplate, fragHandle);
   return fragHandle;
 }
 
-nsIContentHandle*
-nsHtml5TreeBuilder::getFormPointerForContext(nsIContentHandle* aContext)
+nsIContent**
+nsHtml5TreeBuilder::getFormPointerForContext(nsIContent** aContext)
 {
-  MOZ_ASSERT(mBuilder, "Must have builder.");
   if (!aContext) {
     return nullptr;
   }
 
   MOZ_ASSERT(NS_IsMainThread());
 
-  // aContext must always be an element that already exists
-  // in the document.
-  nsIContent* contextNode = static_cast<nsIContent*>(aContext);
+  // aContext must always be a handle to an element that already exists
+  // in the document. It must never be an empty handle.
+  nsIContent* contextNode = *aContext;
   nsIContent* currentAncestor = contextNode;
 
   // We traverse the ancestors of the context node to find the nearest
   // form pointer. This traversal is why aContext must not be an emtpy handle.
   nsIContent* nearestForm = nullptr;
   while (currentAncestor) {
     if (currentAncestor->IsHTML(nsGkAtoms::form)) {
       nearestForm = currentAncestor;
@@ -1059,25 +785,26 @@ nsHtml5TreeBuilder::getFormPointerForCon
     }
     currentAncestor = currentAncestor->GetParent();
   }
 
   if (!nearestForm) {
     return nullptr;
   }
 
-  return nearestForm;
+  nsIContent** formPointer = AllocateContentHandle();
+  *formPointer = nearestForm;
+  return formPointer;
 }
 
 // Error reporting
 
 void
 nsHtml5TreeBuilder::EnableViewSource(nsHtml5Highlighter* aHighlighter)
 {
-  MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
   mViewSource = aHighlighter;
 }
 
 void
 nsHtml5TreeBuilder::errStrayStartTag(nsIAtom* aName)
 {
   if (MOZ_UNLIKELY(mViewSource)) {
     mViewSource->AddErrorToCurrentRun("errStrayStartTag2", aName);
--- a/parser/html/nsHtml5TreeBuilderHSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderHSupplement.h
@@ -1,43 +1,39 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #define NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH 512
 
   private:
-    nsHtml5OplessBuilder*                  mBuilder;
-    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-    // If mBuilder is not null, the tree op machinery is not in use and
-    // the fields below aren't in use, either.
-    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     nsHtml5Highlighter*                    mViewSource;
     nsTArray<nsHtml5TreeOperation>         mOpQueue;
     nsTArray<nsHtml5SpeculativeLoad>       mSpeculativeLoadQueue;
     nsAHtml5TreeOpSink*                    mOpSink;
     nsAutoArrayPtr<nsIContent*>            mHandles;
     int32_t                                mHandlesUsed;
     nsTArray<nsAutoArrayPtr<nsIContent*> > mOldHandles;
     nsHtml5TreeOpStage*                    mSpeculativeLoadStage;
+    nsIContent**                           mDeepTreeSurrogateParent;
     bool                                   mCurrentHtmlScriptIsAsyncOrDefer;
     bool                                   mPreventScriptExecution;
 #ifdef DEBUG
     bool                                   mActive;
 #endif
 
     // DocumentModeHandler
     /**
      * Tree builder uses this to report quirkiness of the document
      */
     void documentMode(nsHtml5DocumentMode m);
 
-    nsIContentHandle* getDocumentFragmentForTemplate(nsIContentHandle* aTemplate);
+    nsIContent** getDocumentFragmentForTemplate(nsIContent** aTemplate);
 
-    nsIContentHandle* getFormPointerForContext(nsIContentHandle* aContext);
+    nsIContent** getFormPointerForContext(nsIContent** aContext);
 
     /**
      * Using nsIContent** instead of nsIContent* is the parser deals with DOM
      * nodes in a way that works off the main thread. Non-main-thread code
      * can't refcount or otherwise touch nsIContent objects in any way.
      * Yet, the off-the-main-thread code needs to have a way to hold onto a
      * particular node and repeatedly operate on the same node.
      *
@@ -48,57 +44,47 @@
      * nsIContent** immediately and a tree op is enqueued for later allocating
      * an actual nsIContent object and writing a pointer to it into the memory
      * location pointed to by the nsIContent**.
      *
      * Since tree ops are in a queue, the node creating tree op will always
      * run before tree ops that try to further operate on the node that the
      * nsIContent** is a handle to.
      *
-     * On-the-main-thread parts of the parser use nsIContent* instead of
-     * nsIContent**. Since both cases share the same parser core, the parser
-     * core casts both to nsIContentHandle*.
+     * On-the-main-thread parts of the parser use the same mechanism in order
+     * to avoid having to have duplicate code paths for on-the-main-thread and
+     * off-the-main-thread tree builder instances.)
      */
-    nsIContentHandle* AllocateContentHandle();
+    nsIContent** AllocateContentHandle();
     
     void accumulateCharactersForced(const char16_t* aBuf, int32_t aStart, int32_t aLength)
     {
       accumulateCharacters(aBuf, aStart, aLength);
     }
 
-    void MarkAsBrokenAndRequestSuspension(nsresult aRv)
-    {
-      mBuilder->MarkAsBroken(aRv);
-      requestSuspension();
-    }
-
   public:
 
-    nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder);
-
     nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink,
                        nsHtml5TreeOpStage* aStage);
 
     ~nsHtml5TreeBuilder();
     
     void StartPlainTextViewSource(const nsAutoString& aTitle);
 
     void StartPlainText();
 
     void StartPlainTextBody();
 
     bool HasScript();
     
-    void SetOpSink(nsAHtml5TreeOpSink* aOpSink)
-    {
+    void SetOpSink(nsAHtml5TreeOpSink* aOpSink) {
       mOpSink = aOpSink;
     }
 
-    void ClearOps()
-    {
+    void ClearOps() {
       mOpQueue.Clear();
     }
     
     bool Flush(bool aDiscretionary = false);
     
     void FlushLoads();
 
     void SetDocumentCharset(nsACString& aCharset, int32_t aCharsetSource);
@@ -112,26 +98,20 @@
     void MaybeComplainAboutCharset(const char* aMsgId,
                                    bool aError,
                                    int32_t aLineNumber);
 
     void AddSnapshotToScript(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine);
 
     void DropHandles();
 
-    void SetPreventScriptExecution(bool aPrevent)
-    {
+    void SetPreventScriptExecution(bool aPrevent) {
       mPreventScriptExecution = aPrevent;
     }
 
-    bool HasBuilder()
-    {
-      return mBuilder;
-    }
-
     void EnableViewSource(nsHtml5Highlighter* aHighlighter);
 
     void errStrayStartTag(nsIAtom* aName);
 
     void errStrayEndTag(nsIAtom* aName);
 
     void errUnclosedElements(int32_t aIndex, nsIAtom* aName);
 
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -8,16 +8,18 @@
 #include "mozilla/Likely.h"
 
 #include "nsError.h"
 #include "nsHtml5TreeOpExecutor.h"
 #include "nsScriptLoader.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsIContentViewer.h"
 #include "nsIDocShellTreeItem.h"
+#include "nsIStyleSheetLinkingElement.h"
+#include "nsStyleLinkElement.h"
 #include "nsIDocShell.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIWebShellServices.h"
 #include "nsContentUtils.h"
 #include "mozAutoDocUpdate.h"
 #include "nsNetUtil.h"
 #include "nsHtml5Parser.h"
@@ -28,20 +30,23 @@
 #include "GeckoProfiler.h"
 #include "nsIScriptError.h"
 #include "nsIScriptContext.h"
 #include "mozilla/Preferences.h"
 #include "nsIHTMLDocument.h"
 
 using namespace mozilla;
 
+NS_IMPL_CYCLE_COLLECTION_INHERITED_1(nsHtml5TreeOpExecutor, nsContentSink,
+                                     mOwnedElements)
+
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHtml5TreeOpExecutor)
   NS_INTERFACE_TABLE_INHERITED1(nsHtml5TreeOpExecutor, 
                                 nsIContentSink)
-NS_INTERFACE_TABLE_TAIL_INHERITING(nsHtml5DocumentBuilder)
+NS_INTERFACE_TABLE_TAIL_INHERITING(nsContentSink)
 
 NS_IMPL_ADDREF_INHERITED(nsHtml5TreeOpExecutor, nsContentSink)
 
 NS_IMPL_RELEASE_INHERITED(nsHtml5TreeOpExecutor, nsContentSink)
 
 class nsHtml5ExecutorReflusher : public nsRunnable
 {
   private:
@@ -55,20 +60,20 @@ class nsHtml5ExecutorReflusher : public 
       mExecutor->RunFlushLoop();
       return NS_OK;
     }
 };
 
 static mozilla::LinkedList<nsHtml5TreeOpExecutor>* gBackgroundFlushList = nullptr;
 static nsITimer* gFlushTimer = nullptr;
 
-nsHtml5TreeOpExecutor::nsHtml5TreeOpExecutor()
-  : nsHtml5DocumentBuilder(false)
-  , mPreloadedURLs(23)  // Mean # of preloadable resources per page on dmoz
+nsHtml5TreeOpExecutor::nsHtml5TreeOpExecutor(bool aRunsToCompletion)
+  : mPreloadedURLs(23)  // Mean # of preloadable resources per page on dmoz
 {
+  mRunsToCompletion = aRunsToCompletion;
   // zeroing operator new for everything else
 }
 
 nsHtml5TreeOpExecutor::~nsHtml5TreeOpExecutor()
 {
   if (gBackgroundFlushList && isInList()) {
     mOpQueue.Clear();
     removeFrom(*gBackgroundFlushList);
@@ -203,26 +208,44 @@ void
 nsHtml5TreeOpExecutor::FlushPendingNotifications(mozFlushType aType)
 {
   if (aType >= Flush_InterruptibleLayout) {
     // Bug 577508 / 253951
     nsContentSink::StartLayout(true);
   }
 }
 
+void
+nsHtml5TreeOpExecutor::SetDocumentCharsetAndSource(nsACString& aCharset, int32_t aCharsetSource)
+{
+  if (mDocument) {
+    mDocument->SetDocumentCharacterSetSource(aCharsetSource);
+    mDocument->SetDocumentCharacterSet(aCharset);
+  }
+}
+
 nsISupports*
 nsHtml5TreeOpExecutor::GetTarget()
 {
   return mDocument;
 }
 
+// nsContentSink overrides
+
+void
+nsHtml5TreeOpExecutor::UpdateChildCounts()
+{
+  // No-op
+}
+
 nsresult
 nsHtml5TreeOpExecutor::MarkAsBroken(nsresult aReason)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  NS_ASSERTION(!mRunsToCompletion, "Fragment parsers can't be broken!");
   mBroken = aReason;
   if (mStreamParser) {
     mStreamParser->Terminate();
   }
   // We are under memory pressure, but let's hope the following allocation
   // works out so that we get to terminate and clean up the parser from
   // a safer point.
   if (mParser) { // can mParser ever be null here?
@@ -230,16 +253,22 @@ nsHtml5TreeOpExecutor::MarkAsBroken(nsre
       NS_NewRunnableMethod(GetParser(), &nsHtml5Parser::Terminate);
     if (NS_FAILED(NS_DispatchToMainThread(terminator))) {
       NS_WARNING("failed to dispatch executor flush event");
     }
   }
   return aReason;
 }
 
+nsresult
+nsHtml5TreeOpExecutor::FlushTags()
+{
+  return NS_OK;
+}
+
 void
 FlushTimerCallback(nsITimer* aTimer, void* aClosure)
 {
   nsRefPtr<nsHtml5TreeOpExecutor> ex = gBackgroundFlushList->popFirst();
   if (ex) {
     ex->RunFlushLoop();
   }
   if (gBackgroundFlushList && gBackgroundFlushList->isEmpty()) {
@@ -273,16 +302,71 @@ nsHtml5TreeOpExecutor::ContinueInterrupt
       // See bug 734015.
       gFlushTimer->InitWithFuncCallback(FlushTimerCallback, nullptr,
                                         50, nsITimer::TYPE_REPEATING_SLACK);
     }
   }
 }
 
 void
+nsHtml5TreeOpExecutor::UpdateStyleSheet(nsIContent* aElement)
+{
+  // Break out of the doc update created by Flush() to zap a runnable 
+  // waiting to call UpdateStyleSheet without the right observer
+  EndDocUpdate();
+
+  if (MOZ_UNLIKELY(!mParser)) {
+    // EndDocUpdate ran stuff that called nsIParser::Terminate()
+    return;
+  }
+
+  nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aElement));
+  NS_ASSERTION(ssle, "Node didn't QI to style.");
+
+  ssle->SetEnableUpdates(true);
+
+  bool willNotify;
+  bool isAlternate;
+  nsresult rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this,
+                                       &willNotify,
+                                       &isAlternate);
+  if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mRunsToCompletion) {
+    ++mPendingSheetCount;
+    mScriptLoader->AddExecuteBlocker();
+  }
+
+  if (aElement->IsHTML(nsGkAtoms::link)) {
+    // look for <link rel="next" href="url">
+    nsAutoString relVal;
+    aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal);
+    if (!relVal.IsEmpty()) {
+      uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(relVal);
+      bool hasPrefetch = linkTypes & nsStyleLinkElement::ePREFETCH;
+      if (hasPrefetch || (linkTypes & nsStyleLinkElement::eNEXT)) {
+        nsAutoString hrefVal;
+        aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
+        if (!hrefVal.IsEmpty()) {
+          PrefetchHref(hrefVal, aElement, hasPrefetch);
+        }
+      }
+      if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
+        nsAutoString hrefVal;
+        aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
+        if (!hrefVal.IsEmpty()) {
+          PrefetchDNS(hrefVal);
+        }
+      }
+    }
+  }
+
+  // Re-open update
+  BeginDocUpdate();
+}
+
+void
 nsHtml5TreeOpExecutor::FlushSpeculativeLoads()
 {
   nsTArray<nsHtml5SpeculativeLoad> speculativeLoadQueue;
   mStage.MoveSpeculativeLoadsTo(speculativeLoadQueue);
   const nsHtml5SpeculativeLoad* start = speculativeLoadQueue.Elements();
   const nsHtml5SpeculativeLoad* end = start + speculativeLoadQueue.Length();
   for (nsHtml5SpeculativeLoad* iter = const_cast<nsHtml5SpeculativeLoad*>(start);
        iter < end;
@@ -420,17 +504,17 @@ nsHtml5TreeOpExecutor::RunFlushLoop()
     mFlushState = eInFlush;
 
     nsIContent* scriptElement = nullptr;
     
     BeginDocUpdate();
 
     uint32_t numberOfOpsToFlush = mOpQueue.Length();
 
-    SetAppendBatchCapacity(numberOfOpsToFlush * 2);
+    mElementsSeenInThisAppendBatch.SetCapacity(numberOfOpsToFlush * 2);
 
     const nsHtml5TreeOperation* first = mOpQueue.Elements();
     const nsHtml5TreeOperation* last = first + numberOfOpsToFlush - 1;
     for (nsHtml5TreeOperation* iter = const_cast<nsHtml5TreeOperation*>(first);;) {
       if (MOZ_UNLIKELY(!mParser)) {
         // The previous tree op caused a call to nsIParser::Terminate().
         break;
       }
@@ -524,17 +608,17 @@ nsHtml5TreeOpExecutor::FlushDocumentWrit
 #endif
   
   nsIContent* scriptElement = nullptr;
   
   BeginDocUpdate();
 
   uint32_t numberOfOpsToFlush = mOpQueue.Length();
 
-  SetAppendBatchCapacity(numberOfOpsToFlush * 2);
+  mElementsSeenInThisAppendBatch.SetCapacity(numberOfOpsToFlush * 2);
 
   const nsHtml5TreeOperation* start = mOpQueue.Elements();
   const nsHtml5TreeOperation* end = start + numberOfOpsToFlush;
   for (nsHtml5TreeOperation* iter = const_cast<nsHtml5TreeOperation*>(start);
        iter < end;
        ++iter) {
     if (MOZ_UNLIKELY(!mParser)) {
       // The previous tree op caused a call to nsIParser::Terminate().
@@ -580,16 +664,36 @@ nsHtml5TreeOpExecutor::IsScriptEnabled()
     NS_ENSURE_TRUE(globalObject, true);
   }
   NS_ENSURE_TRUE(globalObject && globalObject->GetGlobalJSObject(), true);
   return nsContentUtils::GetSecurityManager()->
            ScriptAllowed(globalObject->GetGlobalJSObject());
 }
 
 void
+nsHtml5TreeOpExecutor::SetDocumentMode(nsHtml5DocumentMode m)
+{
+  nsCompatibility mode = eCompatibility_NavQuirks;
+  switch (m) {
+    case STANDARDS_MODE:
+      mode = eCompatibility_FullStandards;
+      break;
+    case ALMOST_STANDARDS_MODE:
+      mode = eCompatibility_AlmostStandards;
+      break;
+    case QUIRKS_MODE:
+      mode = eCompatibility_NavQuirks;
+      break;
+  }
+  nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(mDocument);
+  NS_ASSERTION(htmlDocument, "Document didn't QI into HTML document.");
+  htmlDocument->SetCompatibilityMode(mode);
+}
+
+void
 nsHtml5TreeOpExecutor::StartLayout() {
   if (mLayoutStarted || !mDocument) {
     return;
   }
 
   EndDocUpdate();
 
   if (MOZ_UNLIKELY(!mParser)) {
@@ -661,16 +765,25 @@ nsHtml5TreeOpExecutor::RunScript(nsICont
     // mParser may have been nulled out by now, but the flusher deals
 
     // If this event isn't needed, it doesn't do anything. It is sometimes
     // necessary for the parse to continue after complex situations.
     nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync();
   }
 }
 
+nsresult
+nsHtml5TreeOpExecutor::Init(nsIDocument* aDoc,
+                            nsIURI* aURI,
+                            nsISupports* aContainer,
+                            nsIChannel* aChannel)
+{
+  return nsContentSink::Init(aDoc, aURI, aContainer, aChannel);
+}
+
 void
 nsHtml5TreeOpExecutor::Start()
 {
   NS_PRECONDITION(!mStarted, "Tried to start when already started.");
   mStarted = true;
 }
 
 void
@@ -768,16 +881,41 @@ nsHtml5TreeOpExecutor::ComplainAboutBogu
 nsHtml5Parser*
 nsHtml5TreeOpExecutor::GetParser()
 {
   MOZ_ASSERT(!mRunsToCompletion);
   return static_cast<nsHtml5Parser*>(mParser.get());
 }
 
 void
+nsHtml5TreeOpExecutor::Reset()
+{
+  MOZ_ASSERT(mRunsToCompletion);
+  DropHeldElements();
+  mOpQueue.Clear();
+  mStarted = false;
+  mFlushState = eNotFlushing;
+  mRunFlushLoopOnStack = false;
+  MOZ_ASSERT(!mReadingFromStage);
+  MOZ_ASSERT(NS_SUCCEEDED(mBroken));
+}
+
+void
+nsHtml5TreeOpExecutor::DropHeldElements()
+{
+  mScriptLoader = nullptr;
+  mDocument = nullptr;
+  mNodeInfoManager = nullptr;
+  mCSSLoader = nullptr;
+  mDocumentURI = nullptr;
+  mDocShell = nullptr;
+  mOwnedElements.Clear();
+}
+
+void
 nsHtml5TreeOpExecutor::MoveOpsFrom(nsTArray<nsHtml5TreeOperation>& aOpQueue)
 {
   NS_PRECONDITION(mFlushState == eNotFlushing, "mOpQueue modified during tree op execution.");
   if (mOpQueue.IsEmpty()) {
     mOpQueue.SwapElements(aOpQueue);
     return;
   }
   mOpQueue.MoveElementsFrom(aOpQueue);
--- a/parser/html/nsHtml5TreeOpExecutor.h
+++ b/parser/html/nsHtml5TreeOpExecutor.h
@@ -1,50 +1,61 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsHtml5TreeOpExecutor_h
 #define nsHtml5TreeOpExecutor_h
 
 #include "nsIAtom.h"
+#include "nsNameSpaceManager.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "nsHtml5TreeOperation.h"
 #include "nsHtml5SpeculativeLoad.h"
+#include "nsHtml5PendingNotification.h"
 #include "nsTArray.h"
 #include "nsContentSink.h"
 #include "nsNodeInfoManager.h"
 #include "nsHtml5DocumentMode.h"
 #include "nsIScriptElement.h"
 #include "nsIParser.h"
 #include "nsAHtml5TreeOpSink.h"
 #include "nsHtml5TreeOpStage.h"
 #include "nsIURI.h"
 #include "nsTHashtable.h"
 #include "nsHashKeys.h"
 #include "mozilla/LinkedList.h"
-#include "nsHtml5DocumentBuilder.h"
 
 class nsHtml5Parser;
 class nsHtml5TreeBuilder;
 class nsHtml5Tokenizer;
 class nsHtml5StreamParser;
 
-class nsHtml5TreeOpExecutor : public nsHtml5DocumentBuilder,
+typedef nsIContent* nsIContentPtr;
+
+enum eHtml5FlushState {
+  eNotFlushing = 0,  // not flushing
+  eInFlush = 1,      // the Flush() method is on the call stack
+  eInDocUpdate = 2,  // inside an update batch on the document
+  eNotifying = 3     // flushing pending append notifications
+};
+
+class nsHtml5TreeOpExecutor : public nsContentSink,
                               public nsIContentSink,
                               public nsAHtml5TreeOpSink,
                               public mozilla::LinkedListElement<nsHtml5TreeOpExecutor>
 {
   friend class nsHtml5FlushLoopGuard;
 
   public:
     NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
     NS_DECL_ISUPPORTS_INHERITED
+    NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHtml5TreeOpExecutor, nsContentSink)
 
   private:
     static bool        sExternalViewSource;
 #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
     static uint32_t    sAppendBatchMaxSize;
     static uint32_t    sAppendBatchSlotsExamined;
     static uint32_t    sAppendBatchExaminations;
     static uint32_t    sLongestTimeOffTheEventLoop;
@@ -53,17 +64,20 @@ class nsHtml5TreeOpExecutor : public nsH
 
     /**
      * Whether EOF needs to be suppressed
      */
     bool                                 mSuppressEOF;
     
     bool                                 mReadingFromStage;
     nsTArray<nsHtml5TreeOperation>       mOpQueue;
+    nsTArray<nsIContentPtr>              mElementsSeenInThisAppendBatch;
+    nsTArray<nsHtml5PendingNotification> mPendingNotifications;
     nsHtml5StreamParser*                 mStreamParser;
+    nsTArray<nsCOMPtr<nsIContent> >      mOwnedElements;
     
     /**
      * URLs already preloaded/preloading.
      */
     nsTHashtable<nsCStringHashKey> mPreloadedURLs;
 
     nsCOMPtr<nsIURI> mSpeculationBaseURI;
 
@@ -71,29 +85,44 @@ class nsHtml5TreeOpExecutor : public nsH
 
     /**
      * Whether the parser has started
      */
     bool                          mStarted;
 
     nsHtml5TreeOpStage            mStage;
 
+    eHtml5FlushState              mFlushState;
+
     bool                          mRunFlushLoopOnStack;
 
     bool                          mCallContinueInterruptedParsingIfEnabled;
 
     /**
+     * Non-NS_OK if this parser should refuse to process any more input.
+     * For example, the parser needs to be marked as broken if it drops some
+     * input due to a memory allocation failure. In such a case, the whole
+     * parser needs to be marked as broken, because some input has been lost
+     * and parsing more input could lead to a DOM where pieces of HTML source
+     * that weren't supposed to become scripts become scripts.
+     *
+     * Since NS_OK is actually 0, zeroing operator new takes care of
+     * initializing this.
+     */
+    nsresult                      mBroken;
+
+    /**
      * Whether this executor has already complained about matters related
      * to character encoding declarations.
      */
     bool                          mAlreadyComplainedAboutCharset;
 
   public:
   
-    nsHtml5TreeOpExecutor();
+    nsHtml5TreeOpExecutor(bool aRunsToCompletion = false);
     virtual ~nsHtml5TreeOpExecutor();
   
     // nsIContentSink
 
     /**
      * Unimplemented. For interface compat only.
      */
     NS_IMETHOD WillParse();
@@ -136,44 +165,162 @@ class nsHtml5TreeOpExecutor : public nsH
     	return NS_ERROR_NOT_IMPLEMENTED;
     }
 
     /**
      * Returns the document.
      */
     virtual nsISupports *GetTarget();
   
+    // nsContentSink methods
+    virtual void UpdateChildCounts();
+    virtual nsresult FlushTags();
     virtual void ContinueInterruptedParsingAsync();
  
-    // XXX Does anyone need this?
-    nsIDocShell* GetDocShell()
-    {
+    /**
+     * Sets up style sheet load / parse
+     */
+    void UpdateStyleSheet(nsIContent* aElement);
+
+    // Getters and setters for fields from nsContentSink
+    nsIDocument* GetDocument() {
+      return mDocument;
+    }
+    nsNodeInfoManager* GetNodeInfoManager() {
+      return mNodeInfoManager;
+    }
+    nsIDocShell* GetDocShell() {
       return mDocShell;
     }
 
-    bool IsScriptExecuting()
-    {
+    bool IsScriptExecuting() {
       return IsScriptExecutingImpl();
     }
-
+    
+    void SetNodeInfoManager(nsNodeInfoManager* aManager) {
+      mNodeInfoManager = aManager;
+    }
+    
     // Not from interface
 
-    void SetStreamParser(nsHtml5StreamParser* aStreamParser)
-    {
+    void SetDocumentCharsetAndSource(nsACString& aCharset, int32_t aCharsetSource);
+
+    void SetStreamParser(nsHtml5StreamParser* aStreamParser) {
       mStreamParser = aStreamParser;
     }
     
     void InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState, int32_t aLine);
 
     bool IsScriptEnabled();
 
-    virtual nsresult MarkAsBroken(nsresult aReason);
+    bool BelongsToStringParser() {
+      return mRunsToCompletion;
+    }
+
+    /**
+     * Marks this parser as broken and tells the stream parser (if any) to
+     * terminate.
+     *
+     * @return aReason for convenience
+     */
+    nsresult MarkAsBroken(nsresult aReason);
+
+    /**
+     * Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0)
+     * value if broken.
+     */
+    inline nsresult IsBroken() {
+      return mBroken;
+    }
+
+    inline void BeginDocUpdate() {
+      NS_PRECONDITION(mFlushState == eInFlush, "Tried to double-open update.");
+      NS_PRECONDITION(mParser, "Started update without parser.");
+      mFlushState = eInDocUpdate;
+      mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
+    }
+
+    inline void EndDocUpdate() {
+      NS_PRECONDITION(mFlushState != eNotifying, "mFlushState out of sync");
+      if (mFlushState == eInDocUpdate) {
+        FlushPendingAppendNotifications();
+        mFlushState = eInFlush;
+        mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
+      }
+    }
+
+    void PostPendingAppendNotification(nsIContent* aParent, nsIContent* aChild) {
+      bool newParent = true;
+      const nsIContentPtr* first = mElementsSeenInThisAppendBatch.Elements();
+      const nsIContentPtr* last = first + mElementsSeenInThisAppendBatch.Length() - 1;
+      for (const nsIContentPtr* iter = last; iter >= first; --iter) {
+#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
+        sAppendBatchSlotsExamined++;
+#endif
+        if (*iter == aParent) {
+          newParent = false;
+          break;
+        }
+      }
+      if (aChild->IsElement()) {
+        mElementsSeenInThisAppendBatch.AppendElement(aChild);
+      }
+      mElementsSeenInThisAppendBatch.AppendElement(aParent);
+      if (newParent) {
+        mPendingNotifications.AppendElement(aParent);
+      }
+#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
+      sAppendBatchExaminations++;
+#endif
+    }
+
+    void FlushPendingAppendNotifications() {
+      NS_PRECONDITION(mFlushState == eInDocUpdate, "Notifications flushed outside update");
+      mFlushState = eNotifying;
+      const nsHtml5PendingNotification* start = mPendingNotifications.Elements();
+      const nsHtml5PendingNotification* end = start + mPendingNotifications.Length();
+      for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) {
+        iter->Fire();
+      }
+      mPendingNotifications.Clear();
+#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
+      if (mElementsSeenInThisAppendBatch.Length() > sAppendBatchMaxSize) {
+        sAppendBatchMaxSize = mElementsSeenInThisAppendBatch.Length();
+      }
+#endif
+      mElementsSeenInThisAppendBatch.Clear();
+      NS_ASSERTION(mFlushState == eNotifying, "mFlushState out of sync");
+      mFlushState = eInDocUpdate;
+    }
+    
+    inline bool HaveNotified(nsIContent* aNode) {
+      NS_PRECONDITION(aNode, "HaveNotified called with null argument.");
+      const nsHtml5PendingNotification* start = mPendingNotifications.Elements();
+      const nsHtml5PendingNotification* end = start + mPendingNotifications.Length();
+      for (;;) {
+        nsIContent* parent = aNode->GetParent();
+        if (!parent) {
+          return true;
+        }
+        for (nsHtml5PendingNotification* iter = (nsHtml5PendingNotification*)start; iter < end; ++iter) {
+          if (iter->Contains(parent)) {
+            return iter->HaveNotifiedIndex(parent->IndexOf(aNode));
+          }
+        }
+        aNode = parent;
+      }
+    }
 
     void StartLayout();
     
+    void SetDocumentMode(nsHtml5DocumentMode m);
+
+    nsresult Init(nsIDocument* aDoc, nsIURI* aURI,
+                  nsISupports* aContainer, nsIChannel* aChannel);
+
     void FlushSpeculativeLoads();
                   
     void RunFlushLoop();
 
     void FlushDocumentWrite();
 
     void MaybeSuspend();
 
@@ -184,61 +331,62 @@ class nsHtml5TreeOpExecutor : public nsH
                               uint32_t aLineNumber);
 
     void MaybeComplainAboutCharset(const char* aMsgId,
                                    bool aError,
                                    uint32_t aLineNumber);
 
     void ComplainAboutBogusProtocolCharset(nsIDocument* aDoc);
 
-    bool IsComplete()
-    {
+    bool IsComplete() {
       return !mParser;
     }
     
-    bool HasStarted()
-    {
+    bool HasStarted() {
       return mStarted;
     }
     
-    bool IsFlushing()
-    {
+    bool IsFlushing() {
       return mFlushState >= eInFlush;
     }
 
 #ifdef DEBUG
-    bool IsInFlushLoop()
-    {
+    bool IsInFlushLoop() {
       return mRunFlushLoopOnStack;
     }
 #endif
     
     void RunScript(nsIContent* aScriptElement);
     
+    void Reset();
+    
+    inline void HoldElement(nsIContent* aContent) {
+      mOwnedElements.AppendElement(aContent);
+    }
+
+    void DropHeldElements();
+
     /**
      * Flush the operations from the tree operations from the argument
      * queue unconditionally. (This is for the main thread case.)
      */
     virtual void MoveOpsFrom(nsTArray<nsHtml5TreeOperation>& aOpQueue);
     
-    nsHtml5TreeOpStage* GetStage()
-    {
+    nsHtml5TreeOpStage* GetStage() {
       return &mStage;
     }
     
-    void StartReadingFromStage()
-    {
+    void StartReadingFromStage() {
       mReadingFromStage = true;
     }
 
     void StreamEnded();
     
 #ifdef DEBUG
-    void AssertStageEmpty()
-    {
+    void AssertStageEmpty() {
       mStage.AssertEmpty();
     }
 #endif
 
     nsIURI* GetViewSourceBaseURI();
 
     void PreloadScript(const nsAString& aURL,
                        const nsAString& aCharset,
--- a/parser/html/nsHtml5TreeOperation.cpp
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -115,17 +115,17 @@ nsHtml5TreeOperation::~nsHtml5TreeOperat
       break;
   }
 }
 
 nsresult
 nsHtml5TreeOperation::AppendTextToTextNode(const char16_t* aBuffer,
                                            uint32_t aLength,
                                            nsIContent* aTextNode,
-                                           nsHtml5DocumentBuilder* aBuilder)
+                                           nsHtml5TreeOpExecutor* aBuilder)
 {
   NS_PRECONDITION(aTextNode, "Got null text node.");
 
   if (aBuilder->HaveNotified(aTextNode)) {
     // This text node has already been notified on, so it's necessary to
     // notify on the append
     nsresult rv = NS_OK;
     uint32_t oldLength = aTextNode->TextLength();
@@ -147,17 +147,17 @@ nsHtml5TreeOperation::AppendTextToTextNo
   return aTextNode->AppendText(aBuffer, aLength, false);
 }
 
 
 nsresult
 nsHtml5TreeOperation::AppendText(const char16_t* aBuffer,
                                  uint32_t aLength,
                                  nsIContent* aParent,
-                                 nsHtml5DocumentBuilder* aBuilder)
+                                 nsHtml5TreeOpExecutor* aBuilder)
 {
   nsresult rv = NS_OK;
   nsIContent* lastChild = aParent->GetLastChild();
   if (lastChild && lastChild->IsNodeOfType(nsINode::eTEXT)) {
     nsHtml5OtherDocUpdate update(aParent->OwnerDoc(),
                                  aBuilder->GetDocument());
     return AppendTextToTextNode(aBuffer, 
                                 aLength, 
@@ -171,17 +171,17 @@ nsHtml5TreeOperation::AppendText(const c
   NS_ENSURE_SUCCESS(rv, rv);
 
   return Append(text, aParent, aBuilder);
 }
 
 nsresult
 nsHtml5TreeOperation::Append(nsIContent* aNode,
                              nsIContent* aParent,
-                             nsHtml5DocumentBuilder* aBuilder)
+                             nsHtml5TreeOpExecutor* aBuilder)
 {
   nsresult rv = NS_OK;
   nsIDocument* executorDoc = aBuilder->GetDocument();
   NS_ASSERTION(executorDoc, "Null doc on executor");
   nsIDocument* parentDoc = aParent->OwnerDoc();
   NS_ASSERTION(parentDoc, "Null owner doc on old node.");
 
   if (MOZ_LIKELY(executorDoc == parentDoc)) {
@@ -202,17 +202,17 @@ nsHtml5TreeOperation::Append(nsIContent*
     nsNodeUtils::ContentAppended(aParent, aNode, childCount);
   }
   parentDoc->EndUpdate(UPDATE_CONTENT_MODEL);
   return rv;
 }
 
 nsresult
 nsHtml5TreeOperation::AppendToDocument(nsIContent* aNode,
-                                       nsHtml5DocumentBuilder* aBuilder)
+                                       nsHtml5TreeOpExecutor* aBuilder)
 {
   nsresult rv = NS_OK;
   aBuilder->FlushPendingAppendNotifications();
   nsIDocument* doc = aBuilder->GetDocument();
   uint32_t childCount = doc->GetChildCount();
   rv = doc->AppendChildTo(aNode, false);
   NS_ENSURE_SUCCESS(rv, rv);
   nsNodeUtils::ContentInserted(doc, aNode, childCount);
@@ -239,660 +239,541 @@ IsElementOrTemplateContent(nsINode* aNod
       if (fragHost && nsNodeUtils::IsTemplateElement(fragHost)) {
         return true;
       }
     }
   }
   return false;
 }
 
-void
-nsHtml5TreeOperation::Detach(nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder)
-{
-  aBuilder->FlushPendingAppendNotifications();
-  nsCOMPtr<nsINode> parent = aNode->GetParentNode();
-  if (parent) {
-    nsHtml5OtherDocUpdate update(parent->OwnerDoc(),
-        aBuilder->GetDocument());
-    int32_t pos = parent->IndexOf(aNode);
-    NS_ASSERTION((pos >= 0), "Element not found as child of its parent");
-    parent->RemoveChildAt(pos, true);
-  }
-}
-
-nsresult
-nsHtml5TreeOperation::AppendChildrenToNewParent(nsIContent* aNode,
-                                                nsIContent* aParent,
-                                                nsHtml5DocumentBuilder* aBuilder)
-{
-  aBuilder->FlushPendingAppendNotifications();
-
-  nsHtml5OtherDocUpdate update(aParent->OwnerDoc(),
-                               aBuilder->GetDocument());
-
-  uint32_t childCount = aParent->GetChildCount();
-  bool didAppend = false;
-  while (aNode->HasChildren()) {
-    nsCOMPtr<nsIContent> child = aNode->GetFirstChild();
-    aNode->RemoveChildAt(0, true);
-    nsresult rv = aParent->AppendChildTo(child, false);
-    NS_ENSURE_SUCCESS(rv, rv);
-    didAppend = true;
-  }
-  if (didAppend) {
-    nsNodeUtils::ContentAppended(aParent, aParent->GetChildAt(childCount),
-                                 childCount);
-  }
-  return NS_OK;
-}
-
-nsresult
-nsHtml5TreeOperation::FosterParent(nsIContent* aNode,
-                                   nsIContent* aParent,
-                                   nsIContent* aTable,
-                                   nsHtml5DocumentBuilder* aBuilder)
-{
-  nsIContent* foster = aTable->GetParent();
-
-  if (IsElementOrTemplateContent(foster)) {
-    aBuilder->FlushPendingAppendNotifications();
-
-    nsHtml5OtherDocUpdate update(foster->OwnerDoc(),
-                                 aBuilder->GetDocument());
-
-    uint32_t pos = foster->IndexOf(aTable);
-    nsresult rv = foster->InsertChildAt(aNode, pos, false);
-    NS_ENSURE_SUCCESS(rv, rv);
-    nsNodeUtils::ContentInserted(foster, aNode, pos);
-    return rv;
-  }
-
-  return Append(aNode, aParent, aBuilder);
-}
-
-nsresult
-nsHtml5TreeOperation::AddAttributes(nsIContent* aNode,
-                                    nsHtml5HtmlAttributes* aAttributes,
-                                    nsHtml5DocumentBuilder* aBuilder)
-{
-  dom::Element* node = aNode->AsElement();
-  nsHtml5OtherDocUpdate update(node->OwnerDoc(),
-                               aBuilder->GetDocument());
-
-  int32_t len = aAttributes->getLength();
-  for (int32_t i = len; i > 0;) {
-    --i;
-    // prefix doesn't need regetting. it is always null or a static atom
-    // local name is never null
-    nsCOMPtr<nsIAtom> localName =
-      Reget(aAttributes->getLocalNameNoBoundsCheck(i));
-    int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
-    if (!node->HasAttr(nsuri, localName)) {
-      // prefix doesn't need regetting. it is always null or a static atom
-      // local name is never null
-      node->SetAttr(nsuri,
-                    localName,
-                    aAttributes->getPrefixNoBoundsCheck(i),
-                    *(aAttributes->getValueNoBoundsCheck(i)),
-                    true);
-      // XXX what to do with nsresult?
-    }
-  }
-  return NS_OK;
-}
-
-
-nsIContent*
-nsHtml5TreeOperation::CreateElement(int32_t aNs,
-                                    nsIAtom* aName,
-                                    nsHtml5HtmlAttributes* aAttributes,
-                                    mozilla::dom::FromParser aFromParser,
-                                    nsHtml5DocumentBuilder* aBuilder)
-{
-  bool isKeygen = (aName == nsHtml5Atoms::keygen && aNs == kNameSpaceID_XHTML);
-  if (MOZ_UNLIKELY(isKeygen)) {
-    aName = nsHtml5Atoms::select;
-  }
-
-  nsCOMPtr<dom::Element> newContent;
-  nsCOMPtr<nsINodeInfo> nodeInfo = aBuilder->GetNodeInfoManager()->
-    GetNodeInfo(aName, nullptr, aNs, nsIDOMNode::ELEMENT_NODE);
-  NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
-  NS_NewElement(getter_AddRefs(newContent),
-                nodeInfo.forget(),
-                aFromParser);
-  NS_ASSERTION(newContent, "Element creation created null pointer.");
-
-  aBuilder->HoldElement(newContent);
-
-  if (MOZ_UNLIKELY(aName == nsHtml5Atoms::style || aName == nsHtml5Atoms::link)) {
-    nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(newContent));
-    if (ssle) {
-      ssle->InitStyleLinkElement(false);
-      ssle->SetEnableUpdates(false);
-    }
-  } else if (MOZ_UNLIKELY(isKeygen)) {
-    // Adapted from CNavDTD
-    nsresult rv;
-    nsCOMPtr<nsIFormProcessor> theFormProcessor =
-      do_GetService(kFormProcessorCID, &rv);
-    if (NS_FAILED(rv)) {
-      return newContent;
-    }
-
-    nsTArray<nsString> theContent;
-    nsAutoString theAttribute;
-
-    (void) theFormProcessor->ProvideContent(NS_LITERAL_STRING("select"),
-                                            theContent,
-                                            theAttribute);
-
-    newContent->SetAttr(kNameSpaceID_None,
-                        nsGkAtoms::moztype,
-                        nullptr,
-                        theAttribute,
-                        false);
-
-    nsCOMPtr<nsINodeInfo> optionNodeInfo =
-      aBuilder->GetNodeInfoManager()->GetNodeInfo(nsHtml5Atoms::option,
-                                                  nullptr,
-                                                  kNameSpaceID_XHTML,
-                                                  nsIDOMNode::ELEMENT_NODE);
-
-    for (uint32_t i = 0; i < theContent.Length(); ++i) {
-      nsCOMPtr<dom::Element> optionElt;
-      nsCOMPtr<nsINodeInfo> ni = optionNodeInfo;
-      NS_NewElement(getter_AddRefs(optionElt),
-                    ni.forget(),
-                    aFromParser);
-      nsRefPtr<nsTextNode> optionText =
-        new nsTextNode(aBuilder->GetNodeInfoManager());
-      (void) optionText->SetText(theContent[i], false);
-      optionElt->AppendChildTo(optionText, false);
-      newContent->AppendChildTo(optionElt, false);
-      newContent->DoneAddingChildren(false);
-    }
-  }
-
-  if (!aAttributes) {
-    return newContent;
-  }
-
-  int32_t len = aAttributes->getLength();
-  for (int32_t i = len; i > 0;) {
-    --i;
-    // prefix doesn't need regetting. it is always null or a static atom
-    // local name is never null
-    nsCOMPtr<nsIAtom> localName =
-      Reget(aAttributes->getLocalNameNoBoundsCheck(i));
-    nsCOMPtr<nsIAtom> prefix = aAttributes->getPrefixNoBoundsCheck(i);
-    int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
-
-    if (aNs == kNameSpaceID_XHTML &&
-        nsHtml5Atoms::a == aName &&
-        nsHtml5Atoms::name == localName) {
-      // This is an HTML5-incompliant Geckoism.
-      // Remove when fixing bug 582361
-      NS_ConvertUTF16toUTF8 cname(*(aAttributes->getValueNoBoundsCheck(i)));
-      NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting()));
-      newContent->SetAttr(nsuri,
-                          localName,
-                          prefix,
-                          uv,
-                          false);
-    } else {
-      nsString& value = *(aAttributes->getValueNoBoundsCheck(i));
-      newContent->SetAttr(nsuri,
-                          localName,
-                          prefix,
-                          value,
-                          false);
-
-      // Custom element prototype swizzling may be needed if there is an
-      // "is" attribute.
-      if (kNameSpaceID_None == nsuri && !prefix && nsGkAtoms::is == localName) {
-        ErrorResult errorResult;
-        newContent->OwnerDoc()->SwizzleCustomElement(newContent,
-                                                     value,
-                                                     newContent->GetNameSpaceID(),
-                                                     errorResult);
-      }
-    }
-  }
-  return newContent;
-}
-
-void
-nsHtml5TreeOperation::SetFormElement(nsIContent* aNode, nsIContent* aParent)
-{
-  nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(aNode));
-  nsCOMPtr<nsIDOMHTMLImageElement> domImageElement = do_QueryInterface(aNode);
-  // NS_ASSERTION(formControl, "Form-associated element did not implement nsIFormControl.");
-  // TODO: uncomment the above line when <keygen> (bug 101019) is supported by Gecko
-  nsCOMPtr<nsIDOMHTMLFormElement> formElement(do_QueryInterface(aParent));
-  NS_ASSERTION(formElement, "The form element doesn't implement nsIDOMHTMLFormElement.");
-  // avoid crashing on <keygen>
-  if (formControl &&
-      !aNode->HasAttr(kNameSpaceID_None, nsGkAtoms::form)) {
-    formControl->SetForm(formElement);
-  } else if (domImageElement) {
-    nsRefPtr<dom::HTMLImageElement> imageElement =
-      static_cast<dom::HTMLImageElement*>(domImageElement.get());
-    MOZ_ASSERT(imageElement);
-    imageElement->SetForm(formElement);
-  }
-}
-
-nsresult
-nsHtml5TreeOperation::AppendIsindexPrompt(nsIContent* parent, nsHtml5DocumentBuilder* aBuilder)
-{
-  nsXPIDLString prompt;
-  nsresult rv =
-      nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
-                                         "IsIndexPromptWithSpace", prompt);
-  uint32_t len = prompt.Length();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  if (!len) {
-    // Don't bother appending a zero-length text node.
-    return NS_OK;
-  }
-  return AppendText(prompt.BeginReading(), len, parent, aBuilder);
-}
-
-nsresult
-nsHtml5TreeOperation::FosterParentText(nsIContent* aStackParent,
-                                       char16_t* aBuffer,
-                                       uint32_t aLength,
-                                       nsIContent* aTable,
-                                       nsHtml5DocumentBuilder* aBuilder)
-{
-  nsresult rv = NS_OK;
-  nsIContent* foster = aTable->GetParent();
-
-  if (IsElementOrTemplateContent(foster)) {
-    aBuilder->FlushPendingAppendNotifications();
-
-    nsHtml5OtherDocUpdate update(foster->OwnerDoc(),
-                                 aBuilder->GetDocument());
-
-    uint32_t pos = foster->IndexOf(aTable);
-
-    nsIContent* previousSibling = aTable->GetPreviousSibling();
-    if (previousSibling && previousSibling->IsNodeOfType(nsINode::eTEXT)) {
-      return AppendTextToTextNode(aBuffer,
-                                  aLength,
-                                  previousSibling,
-                                  aBuilder);
-    }
-
-    nsRefPtr<nsTextNode> text =
-      new nsTextNode(aBuilder->GetNodeInfoManager());
-    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;
-  }
-
-  return AppendText(aBuffer, aLength, aStackParent, aBuilder);
-}
-
-nsresult
-nsHtml5TreeOperation::AppendComment(nsIContent* aParent,
-                                    char16_t* aBuffer,
-                                    int32_t aLength,
-                                    nsHtml5DocumentBuilder* aBuilder)
-{
-  nsRefPtr<dom::Comment> comment =
-    new dom::Comment(aBuilder->GetNodeInfoManager());
-  NS_ASSERTION(comment, "Infallible malloc failed?");
-  nsresult rv = comment->SetText(aBuffer, aLength, false);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return Append(comment, aParent, aBuilder);
-}
-
-nsresult
-nsHtml5TreeOperation::AppendCommentToDocument(char16_t* aBuffer,
-                                              int32_t aLength,
-                                              nsHtml5DocumentBuilder* aBuilder)
-{
-  nsRefPtr<dom::Comment> comment =
-    new dom::Comment(aBuilder->GetNodeInfoManager());
-  NS_ASSERTION(comment, "Infallible malloc failed?");
-  nsresult rv = comment->SetText(aBuffer, aLength, false);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return AppendToDocument(comment, aBuilder);
-}
-
-nsresult
-nsHtml5TreeOperation::AppendDoctypeToDocument(nsIAtom* aName,
-                                              const nsAString& aPublicId,
-                                              const nsAString& aSystemId,
-                                              nsHtml5DocumentBuilder* aBuilder)
-{
-  // Adapted from nsXMLContentSink
-  // Create a new doctype node
-  nsCOMPtr<nsIDOMDocumentType> docType;
-  nsAutoString voidString;
-  voidString.SetIsVoid(true);
-  NS_NewDOMDocumentType(getter_AddRefs(docType),
-                        aBuilder->GetNodeInfoManager(),
-                        aName,
-                        aPublicId,
-                        aSystemId,
-                        voidString);
-  NS_ASSERTION(docType, "Doctype creation failed.");
-  nsCOMPtr<nsIContent> asContent = do_QueryInterface(docType);
-  return AppendToDocument(asContent, aBuilder);
-}
-
-nsIContent*
-nsHtml5TreeOperation::GetDocumentFragmentForTemplate(nsIContent* aNode)
-{
-  dom::HTMLTemplateElement* tempElem =
-    static_cast<dom::HTMLTemplateElement*>(aNode);
-  nsRefPtr<dom::DocumentFragment> frag = tempElem->Content();
-  return frag;
-}
-
-void
-nsHtml5TreeOperation::PreventScriptExecution(nsIContent* aNode)
-{
-  nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode);
-  MOZ_ASSERT(sele);
-  sele->PreventExecution();
-}
-
-void
-nsHtml5TreeOperation::DoneAddingChildren(nsIContent* aNode,
-                                         nsHtml5DocumentBuilder* aBuilder)
-{
-  aNode->DoneAddingChildren(aBuilder->HaveNotified(aNode));
-}
-
-void
-nsHtml5TreeOperation::DoneCreatingElement(nsIContent* aNode)
-{
-  aNode->DoneCreatingElement();
-}
-
-void
-nsHtml5TreeOperation::SvgLoad(nsIContent* aNode)
-{
-  nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(aNode);
-  if (NS_FAILED(NS_DispatchToMainThread(event))) {
-    NS_WARNING("failed to dispatch svg load dispatcher");
-  }
-}
-
-void
-nsHtml5TreeOperation::MarkMalformedIfScript(nsIContent* aNode)
-{
-  nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode);
-  if (sele) {
-    // Make sure to serialize this script correctly, for nice round tripping.
-    sele->SetIsMalformed();
-  }
-}
-
 nsresult
 nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
                               nsIContent** aScriptElement)
 {
+  nsresult rv = NS_OK;
   switch(mOpCode) {
     case eTreeOpAppend: {
       nsIContent* node = *(mOne.node);
       nsIContent* parent = *(mTwo.node);
       return Append(node, parent, aBuilder);
     }
     case eTreeOpDetach: {
       nsIContent* node = *(mOne.node);
-      Detach(node, aBuilder);
+      aBuilder->FlushPendingAppendNotifications();
+      nsCOMPtr<nsINode> parent = node->GetParentNode();
+      if (parent) {
+        nsHtml5OtherDocUpdate update(parent->OwnerDoc(),
+                                     aBuilder->GetDocument());
+        int32_t pos = parent->IndexOf(node);
+        NS_ASSERTION((pos >= 0), "Element not found as child of its parent");
+        parent->RemoveChildAt(pos, true);
+      }
       return NS_OK;
     }
     case eTreeOpAppendChildrenToNewParent: {
       nsCOMPtr<nsIContent> node = *(mOne.node);
       nsIContent* parent = *(mTwo.node);
-      return AppendChildrenToNewParent(node, parent, aBuilder);
+      aBuilder->FlushPendingAppendNotifications();
+
+      nsHtml5OtherDocUpdate update(parent->OwnerDoc(),
+                                   aBuilder->GetDocument());
+
+      uint32_t childCount = parent->GetChildCount();
+      bool didAppend = false;
+      while (node->HasChildren()) {
+        nsCOMPtr<nsIContent> child = node->GetFirstChild();
+        node->RemoveChildAt(0, true);
+        rv = parent->AppendChildTo(child, false);
+        NS_ENSURE_SUCCESS(rv, rv);
+        didAppend = true;
+      }
+      if (didAppend) {
+        nsNodeUtils::ContentAppended(parent, parent->GetChildAt(childCount),
+                                     childCount);
+      }
+      return rv;
     }
     case eTreeOpFosterParent: {
       nsIContent* node = *(mOne.node);
       nsIContent* parent = *(mTwo.node);
       nsIContent* table = *(mThree.node);
-      return FosterParent(node, parent, table, aBuilder);
+      nsIContent* foster = table->GetParent();
+
+      if (IsElementOrTemplateContent(foster)) {
+        aBuilder->FlushPendingAppendNotifications();
+
+        nsHtml5OtherDocUpdate update(foster->OwnerDoc(),
+                                     aBuilder->GetDocument());
+
+        uint32_t pos = foster->IndexOf(table);
+        rv = foster->InsertChildAt(node, pos, false);
+        NS_ENSURE_SUCCESS(rv, rv);
+        nsNodeUtils::ContentInserted(foster, node, pos);
+        return rv;
+      }
+
+      return Append(node, parent, aBuilder);
     }
     case eTreeOpAppendToDocument: {
       nsIContent* node = *(mOne.node);
       return AppendToDocument(node, aBuilder);
     }
     case eTreeOpAddAttributes: {
-      nsIContent* node = *(mOne.node);
+      dom::Element* node = (*(mOne.node))->AsElement();
       nsHtml5HtmlAttributes* attributes = mTwo.attributes;
-      return AddAttributes(node, attributes, aBuilder);
+
+      nsHtml5OtherDocUpdate update(node->OwnerDoc(),
+                                   aBuilder->GetDocument());
+
+      int32_t len = attributes->getLength();
+      for (int32_t i = len; i > 0;) {
+        --i;
+        // prefix doesn't need regetting. it is always null or a static atom
+        // local name is never null
+        nsCOMPtr<nsIAtom> localName =
+          Reget(attributes->getLocalNameNoBoundsCheck(i));
+        int32_t nsuri = attributes->getURINoBoundsCheck(i);
+        if (!node->HasAttr(nsuri, localName)) {
+          // prefix doesn't need regetting. it is always null or a static atom
+          // local name is never null
+          node->SetAttr(nsuri,
+                        localName,
+                        attributes->getPrefixNoBoundsCheck(i),
+                        *(attributes->getValueNoBoundsCheck(i)),
+                        true);
+          // XXX what to do with nsresult?
+        }
+      }
+      
+      return rv;
     }
     case eTreeOpCreateElementNetwork:
     case eTreeOpCreateElementNotNetwork: {
       nsIContent** target = mOne.node;
       int32_t ns = mFour.integer;
       nsCOMPtr<nsIAtom> name = Reget(mTwo.atom);
       nsHtml5HtmlAttributes* attributes = mThree.attributes;
+      
+      bool isKeygen = (name == nsHtml5Atoms::keygen && ns == kNameSpaceID_XHTML);
+      if (MOZ_UNLIKELY(isKeygen)) {
+        name = nsHtml5Atoms::select;
+      }
+      
+      nsCOMPtr<dom::Element> newContent;
+      nsCOMPtr<nsINodeInfo> nodeInfo = aBuilder->GetNodeInfoManager()->
+        GetNodeInfo(name, nullptr, ns, nsIDOMNode::ELEMENT_NODE);
+      NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
+      NS_NewElement(getter_AddRefs(newContent),
+                    nodeInfo.forget(),
+                    (mOpCode == eTreeOpCreateElementNetwork ?
+                     dom::FROM_PARSER_NETWORK
+                     : (aBuilder->BelongsToStringParser() ?
+                        dom::FROM_PARSER_FRAGMENT :
+                        dom::FROM_PARSER_DOCUMENT_WRITE)));
+      NS_ASSERTION(newContent, "Element creation created null pointer.");
 
-      *target = CreateElement(ns,
-                              name,
-                              attributes,
-                              mOpCode == eTreeOpCreateElementNetwork ?
-                                dom::FROM_PARSER_NETWORK :
-                                dom::FROM_PARSER_DOCUMENT_WRITE,
-                              aBuilder);
-      return NS_OK;
+      aBuilder->HoldElement(*target = newContent);      
+
+      if (MOZ_UNLIKELY(name == nsHtml5Atoms::style || name == nsHtml5Atoms::link)) {
+        nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(newContent));
+        if (ssle) {
+          ssle->InitStyleLinkElement(false);
+          ssle->SetEnableUpdates(false);
+        }
+      } else if (MOZ_UNLIKELY(isKeygen)) {
+        // Adapted from CNavDTD
+        nsCOMPtr<nsIFormProcessor> theFormProcessor =
+          do_GetService(kFormProcessorCID, &rv);
+        if (NS_FAILED(rv)) {
+          return NS_OK;
+        }
+
+        nsTArray<nsString> theContent;
+        nsAutoString theAttribute;
+         
+        (void) theFormProcessor->ProvideContent(NS_LITERAL_STRING("select"),
+                                                theContent,
+                                                theAttribute);
+
+        newContent->SetAttr(kNameSpaceID_None, 
+                            nsGkAtoms::moztype, 
+                            nullptr, 
+                            theAttribute,
+                            false);
+
+        nsCOMPtr<nsINodeInfo> optionNodeInfo = 
+          aBuilder->GetNodeInfoManager()->GetNodeInfo(nsHtml5Atoms::option, 
+                                                      nullptr, 
+                                                      kNameSpaceID_XHTML,
+                                                      nsIDOMNode::ELEMENT_NODE);
+                                                      
+        for (uint32_t i = 0; i < theContent.Length(); ++i) {
+          nsCOMPtr<dom::Element> optionElt;
+          nsCOMPtr<nsINodeInfo> ni = optionNodeInfo;
+          NS_NewElement(getter_AddRefs(optionElt), 
+                        ni.forget(),
+                        (mOpCode == eTreeOpCreateElementNetwork ?
+                         dom::FROM_PARSER_NETWORK
+                         : (aBuilder->BelongsToStringParser() ?
+                            dom::FROM_PARSER_FRAGMENT :
+                            dom::FROM_PARSER_DOCUMENT_WRITE)));
+          nsRefPtr<nsTextNode> optionText =
+            new nsTextNode(aBuilder->GetNodeInfoManager());
+          (void) optionText->SetText(theContent[i], false);
+          optionElt->AppendChildTo(optionText, false);
+          newContent->AppendChildTo(optionElt, false);
+          newContent->DoneAddingChildren(false);
+        }
+      }
+
+      if (!attributes) {
+        return rv;
+      }
+
+      int32_t len = attributes->getLength();
+      for (int32_t i = len; i > 0;) {
+        --i;
+        // prefix doesn't need regetting. it is always null or a static atom
+        // local name is never null
+        nsCOMPtr<nsIAtom> localName =
+          Reget(attributes->getLocalNameNoBoundsCheck(i));
+        nsCOMPtr<nsIAtom> prefix = attributes->getPrefixNoBoundsCheck(i);
+        int32_t nsuri = attributes->getURINoBoundsCheck(i);
+
+        if (ns == kNameSpaceID_XHTML &&
+            nsHtml5Atoms::a == name &&
+            nsHtml5Atoms::name == localName) {
+          // This is an HTML5-incompliant Geckoism.
+          // Remove when fixing bug 582361
+          NS_ConvertUTF16toUTF8 cname(*(attributes->getValueNoBoundsCheck(i)));
+          NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting()));
+          newContent->SetAttr(nsuri,
+                              localName,
+                              prefix,
+                              uv,
+                              false);
+        } else {
+          nsString& value = *(attributes->getValueNoBoundsCheck(i));
+
+          newContent->SetAttr(nsuri,
+                              localName,
+                              prefix,
+                              value,
+                              false);
+
+          // Custom element prototype swizzling may be needed if there is an
+          // "is" attribute.
+          if (kNameSpaceID_None == nsuri && !prefix && nsGkAtoms::is == localName) {
+            ErrorResult errorResult;
+            newContent->OwnerDoc()->SwizzleCustomElement(newContent,
+                                                         value,
+                                                         newContent->GetNameSpaceID(),
+                                                         errorResult);
+
+          }
+        }
+      }
+
+      return rv;
     }
     case eTreeOpSetFormElement: {
       nsIContent* node = *(mOne.node);
       nsIContent* parent = *(mTwo.node);
-      SetFormElement(node, parent);
-      return NS_OK;
+      nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(node));
+      nsCOMPtr<nsIDOMHTMLImageElement> domImageElement = do_QueryInterface(node);
+      // NS_ASSERTION(formControl, "Form-associated element did not implement nsIFormControl.");
+      // TODO: uncomment the above line when <keygen> (bug 101019) is supported by Gecko
+      nsCOMPtr<nsIDOMHTMLFormElement> formElement(do_QueryInterface(parent));
+      NS_ASSERTION(formElement, "The form element doesn't implement nsIDOMHTMLFormElement.");
+      // avoid crashing on <keygen>
+      if (formControl &&
+          !node->HasAttr(kNameSpaceID_None, nsGkAtoms::form)) {
+        formControl->SetForm(formElement);
+      } else if (domImageElement) {
+        nsRefPtr<dom::HTMLImageElement> imageElement =
+          static_cast<dom::HTMLImageElement*>(domImageElement.get());
+        MOZ_ASSERT(imageElement);
+        imageElement->SetForm(formElement);
+      }
+
+      return rv;
     }
     case eTreeOpAppendText: {
       nsIContent* parent = *mOne.node;
       char16_t* buffer = mTwo.unicharPtr;
       uint32_t length = mFour.integer;
       return AppendText(buffer, length, parent, aBuilder);
     }
     case eTreeOpAppendIsindexPrompt: {
       nsIContent* parent = *mOne.node;
-      return AppendIsindexPrompt(parent, aBuilder);
+      nsXPIDLString prompt;
+      nsresult rv =
+          nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
+                                             "IsIndexPromptWithSpace", prompt);
+      uint32_t len = prompt.Length();
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+      if (!len) {
+        // Don't bother appending a zero-length text node.
+        return NS_OK;
+      }
+      return AppendText(prompt.BeginReading(), len, parent, aBuilder);
     }
     case eTreeOpFosterParentText: {
       nsIContent* stackParent = *mOne.node;
       char16_t* buffer = mTwo.unicharPtr;
       uint32_t length = mFour.integer;
       nsIContent* table = *mThree.node;
-      return FosterParentText(stackParent, buffer, length, table, aBuilder);
+      nsIContent* foster = table->GetParent();
+
+      if (IsElementOrTemplateContent(foster)) {
+        aBuilder->FlushPendingAppendNotifications();
+
+        nsHtml5OtherDocUpdate update(foster->OwnerDoc(),
+                                     aBuilder->GetDocument());
+
+        uint32_t pos = foster->IndexOf(table);
+
+        nsIContent* previousSibling = table->GetPreviousSibling();
+        if (previousSibling && previousSibling->IsNodeOfType(nsINode::eTEXT)) {
+          return AppendTextToTextNode(buffer, 
+                                      length, 
+                                      previousSibling, 
+                                      aBuilder);
+        }
+        
+        nsRefPtr<nsTextNode> text =
+          new nsTextNode(aBuilder->GetNodeInfoManager());
+        NS_ASSERTION(text, "Infallible malloc failed?");
+        rv = text->SetText(buffer, length, false);
+        NS_ENSURE_SUCCESS(rv, rv);
+        
+        rv = foster->InsertChildAt(text, pos, false);
+        NS_ENSURE_SUCCESS(rv, rv);
+        nsNodeUtils::ContentInserted(foster, text, pos);
+        return rv;
+      }
+      
+      return AppendText(buffer, length, stackParent, aBuilder);
     }
     case eTreeOpAppendComment: {
       nsIContent* parent = *mOne.node;
       char16_t* buffer = mTwo.unicharPtr;
       int32_t length = mFour.integer;
-      return AppendComment(parent, buffer, length, aBuilder);
+      
+      nsRefPtr<dom::Comment> comment =
+        new dom::Comment(aBuilder->GetNodeInfoManager());
+      NS_ASSERTION(comment, "Infallible malloc failed?");
+      rv = comment->SetText(buffer, length, false);
+      NS_ENSURE_SUCCESS(rv, rv);
+      
+      return Append(comment, parent, aBuilder);
     }
     case eTreeOpAppendCommentToDocument: {
       char16_t* buffer = mTwo.unicharPtr;
       int32_t length = mFour.integer;
-      return AppendCommentToDocument(buffer, length, aBuilder);
+      
+      nsRefPtr<dom::Comment> comment =
+        new dom::Comment(aBuilder->GetNodeInfoManager());
+      NS_ASSERTION(comment, "Infallible malloc failed?");
+      rv = comment->SetText(buffer, length, false);
+      NS_ENSURE_SUCCESS(rv, rv);
+      
+      return AppendToDocument(comment, aBuilder);
     }
     case eTreeOpAppendDoctypeToDocument: {
       nsCOMPtr<nsIAtom> name = Reget(mOne.atom);
       nsHtml5TreeOperationStringPair* pair = mTwo.stringPair;
       nsString publicId;
       nsString systemId;
       pair->Get(publicId, systemId);
-      return AppendDoctypeToDocument(name, publicId, systemId, aBuilder);
+      
+      // Adapted from nsXMLContentSink
+      // Create a new doctype node
+      nsCOMPtr<nsIDOMDocumentType> docType;
+      nsAutoString voidString;
+      voidString.SetIsVoid(true);
+      NS_NewDOMDocumentType(getter_AddRefs(docType),
+                            aBuilder->GetNodeInfoManager(),
+                            name,
+                            publicId,
+                            systemId,
+                            voidString);
+      NS_ASSERTION(docType, "Doctype creation failed.");
+      nsCOMPtr<nsIContent> asContent = do_QueryInterface(docType);
+      return AppendToDocument(asContent, aBuilder);
     }
     case eTreeOpGetDocumentFragmentForTemplate: {
-      nsIContent* node = *(mOne.node);
-      *mTwo.node = GetDocumentFragmentForTemplate(node);
-      return NS_OK;
+      dom::HTMLTemplateElement* tempElem =
+        static_cast<dom::HTMLTemplateElement*>(*mOne.node);
+      nsRefPtr<dom::DocumentFragment> frag = tempElem->Content();
+      *mTwo.node = frag.get();
+      return rv;
     }
     case eTreeOpMarkAsBroken: {
       aBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
-      return NS_OK;
+      return rv;
     }
     case eTreeOpRunScript: {
       nsIContent* node = *(mOne.node);
       nsAHtml5TreeBuilderState* snapshot = mTwo.state;
       if (snapshot) {
         aBuilder->InitializeDocWriteParserState(snapshot, mFour.integer);
       }
       *aScriptElement = node;
-      return NS_OK;
+      return rv;
     }
     case eTreeOpRunScriptAsyncDefer: {
       nsIContent* node = *(mOne.node);
       aBuilder->RunScript(node);
-      return NS_OK;
+      return rv;
     }
     case eTreeOpPreventScriptExecution: {
       nsIContent* node = *(mOne.node);
-      PreventScriptExecution(node);
-      return NS_OK;
+      nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
+      MOZ_ASSERT(sele);
+      sele->PreventExecution();
+      return rv;
     }
     case eTreeOpDoneAddingChildren: {
       nsIContent* node = *(mOne.node);
       node->DoneAddingChildren(aBuilder->HaveNotified(node));
-      return NS_OK;
+      return rv;
     }
     case eTreeOpDoneCreatingElement: {
       nsIContent* node = *(mOne.node);
-      DoneCreatingElement(node);
-      return NS_OK;
+      node->DoneCreatingElement();
+      return rv;
     }
     case eTreeOpFlushPendingAppendNotifications: {
       aBuilder->FlushPendingAppendNotifications();
-      return NS_OK;
+      return rv;
     }
     case eTreeOpSetDocumentCharset: {
       char* str = mOne.charPtr;
       int32_t charsetSource = mFour.integer;
       nsDependentCString dependentString(str);
       aBuilder->SetDocumentCharsetAndSource(dependentString, charsetSource);
-      return NS_OK;
+      return rv;
     }
     case eTreeOpNeedsCharsetSwitchTo: {
       char* str = mOne.charPtr;
       int32_t charsetSource = mFour.integer;
       int32_t lineNumber = mTwo.integer;
       aBuilder->NeedsCharsetSwitchTo(str, charsetSource, (uint32_t)lineNumber);
-      return NS_OK;
+      return rv;    
     }
     case eTreeOpUpdateStyleSheet: {
       nsIContent* node = *(mOne.node);
       aBuilder->FlushPendingAppendNotifications();
       aBuilder->UpdateStyleSheet(node);
-      return NS_OK;
+      return rv;
     }
     case eTreeOpProcessMeta: {
       nsIContent* node = *(mOne.node);
-      return aBuilder->ProcessMETATag(node);
+      rv = aBuilder->ProcessMETATag(node);
+      return rv;
     }
     case eTreeOpProcessOfflineManifest: {
       char16_t* str = mOne.unicharPtr;
       nsDependentString dependentString(str);
       aBuilder->ProcessOfflineManifest(dependentString);
-      return NS_OK;
+      return rv;
     }
     case eTreeOpMarkMalformedIfScript: {
       nsIContent* node = *(mOne.node);
-      MarkMalformedIfScript(node);
-      return NS_OK;
+      nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
+      if (sele) {
+        // Make sure to serialize this script correctly, for nice round tripping.
+        sele->SetIsMalformed();
+      }
+      return rv;
     }
     case eTreeOpStreamEnded: {
       aBuilder->DidBuildModel(false); // this causes a notifications flush anyway
-      return NS_OK;
+      return rv;
     }
     case eTreeOpStartLayout: {
       aBuilder->StartLayout(); // this causes a notification flush anyway
-      return NS_OK;
+      return rv;
     }
     case eTreeOpDocumentMode: {
       aBuilder->SetDocumentMode(mOne.mode);
-      return NS_OK;
+      return rv;
     }
     case eTreeOpSetStyleLineNumber: {
       nsIContent* node = *(mOne.node);
       nsCOMPtr<nsIStyleSheetLinkingElement> ssle = do_QueryInterface(node);
       NS_ASSERTION(ssle, "Node didn't QI to style.");
       ssle->SetLineNumber(mFour.integer);
-      return NS_OK;
+      return rv;
     }
     case eTreeOpSetScriptLineNumberAndFreeze: {
       nsIContent* node = *(mOne.node);
       nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
       NS_ASSERTION(sele, "Node didn't QI to script.");
       sele->SetScriptLineNumber(mFour.integer);
       sele->FreezeUriAsyncDefer();
-      return NS_OK;
+      return rv;
     }
     case eTreeOpSvgLoad: {
       nsIContent* node = *(mOne.node);
-      SvgLoad(node);
-      return NS_OK;
+      nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(node);
+      if (NS_FAILED(NS_DispatchToMainThread(event))) {
+        NS_WARNING("failed to dispatch svg load dispatcher");
+      }
+      return rv;
     }
     case eTreeOpMaybeComplainAboutCharset: {
       char* msgId = mOne.charPtr;
       bool error = mTwo.integer;
       int32_t lineNumber = mThree.integer;
       aBuilder->MaybeComplainAboutCharset(msgId, error, (uint32_t)lineNumber);
-      return NS_OK;
+      return rv;
     }
     case eTreeOpAddClass: {
       nsIContent* node = *(mOne.node);
       char16_t* str = mTwo.unicharPtr;
       nsDependentString depStr(str);
       // See viewsource.css for the possible classes
       nsAutoString klass;
       node->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass);
       if (!klass.IsEmpty()) {
         klass.Append(' ');
         klass.Append(depStr);
         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
       } else {
         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, depStr, true);
       }
-      return NS_OK;
+      return rv;
     }
     case eTreeOpAddLineNumberId: {
       nsIContent* node = *(mOne.node);
       int32_t lineNumber = mFour.integer;
       nsAutoString val(NS_LITERAL_STRING("line"));
       val.AppendInt(lineNumber);
       node->SetAttr(kNameSpaceID_None, nsGkAtoms::id, val, true);
-      return NS_OK;
+      return rv;
     }
     case eTreeOpAddViewSourceHref: {
       nsIContent* node = *mOne.node;
       char16_t* buffer = mTwo.unicharPtr;
       int32_t length = mFour.integer;
 
       nsDependentString relative(buffer, length);
 
       nsIDocument* doc = aBuilder->GetDocument();
 
       const nsCString& charset = doc->GetDocumentCharacterSet();
       nsCOMPtr<nsIURI> uri;
-      nsresult rv = NS_NewURI(getter_AddRefs(uri),
-                              relative,
-                              charset.get(),
-                              aBuilder->GetViewSourceBaseURI());
+      rv = NS_NewURI(getter_AddRefs(uri),
+                     relative,
+                     charset.get(),
+                     aBuilder->GetViewSourceBaseURI());
       NS_ENSURE_SUCCESS(rv, NS_OK);
 
       // Reuse the fix for bug 467852
       // URLs that execute script (e.g. "javascript:" URLs) should just be
       // ignored.  There's nothing reasonable we can do with them, and allowing
       // them to execute in the context of the view-source window presents a
       // security risk.  Just return the empty string in this case.
       bool openingExecutesScript = false;
@@ -941,17 +822,16 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
       } else {
         node->SetAttr(kNameSpaceID_None,
                       nsGkAtoms::_class,
                       NS_LITERAL_STRING("error"),
                       true);
       }
 
-      nsresult rv;
       nsXPIDLString message;
       if (otherAtom) {
         const char16_t* params[] = { atom->GetUTF16String(),
                                       otherAtom->GetUTF16String() };
         rv = nsContentUtils::FormatLocalizedString(
           nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, params, message);
         NS_ENSURE_SUCCESS(rv, rv);
       } else if (atom) {
@@ -975,10 +855,11 @@ nsHtml5TreeOperation::Perform(nsHtml5Tre
         node->SetAttr(kNameSpaceID_None, nsGkAtoms::title, message, true);
       }
       return rv;
     }
     default: {
       NS_NOTREACHED("Bogus tree op");
     }
   }
-  return NS_OK; // keep compiler happy
+  return rv; // keep compiler happy
 }
+
--- a/parser/html/nsHtml5TreeOperation.h
+++ b/parser/html/nsHtml5TreeOperation.h
@@ -3,22 +3,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  
 #ifndef nsHtml5TreeOperation_h
 #define nsHtml5TreeOperation_h
 
 #include "nsHtml5DocumentMode.h"
 #include "nsHtml5HtmlAttributes.h"
 #include "nsXPCOMStrings.h"
-#include "mozilla/dom/FromParser.h"
 
 class nsIContent;
 class nsHtml5TreeOpExecutor;
 class nsHtml5StateSnapshot;
-class nsHtml5DocumentBuilder;
 
 enum eHtml5TreeOperation {
 #ifdef DEBUG
   eTreeOpUninitialized,
 #endif
   // main HTML5 ops
   eTreeOpAppend,
   eTreeOpDetach,
@@ -68,171 +66,66 @@ enum eHtml5TreeOperation {
 class nsHtml5TreeOperationStringPair {
   private:
     nsString mPublicId;
     nsString mSystemId;
   public:
     nsHtml5TreeOperationStringPair(const nsAString& aPublicId, 
                                    const nsAString& aSystemId)
       : mPublicId(aPublicId)
-      , mSystemId(aSystemId)
-    {
+      , mSystemId(aSystemId) {
       MOZ_COUNT_CTOR(nsHtml5TreeOperationStringPair);
     }
     
-    ~nsHtml5TreeOperationStringPair()
-    {
+    ~nsHtml5TreeOperationStringPair() {
       MOZ_COUNT_DTOR(nsHtml5TreeOperationStringPair);    
     }
     
-    inline void Get(nsAString& aPublicId, nsAString& aSystemId)
-    {
+    inline void Get(nsAString& aPublicId, nsAString& aSystemId) {
       aPublicId.Assign(mPublicId);
       aSystemId.Assign(mSystemId);
     }
 };
 
 class nsHtml5TreeOperation {
 
   public:
-    /**
-     * Atom is used inside the parser core are either static atoms that are
-     * the same as Gecko-wide static atoms or they are dynamic atoms scoped by
-     * both thread and parser to a particular nsHtml5AtomTable. In order to
-     * such scoped atoms coming into contact with the rest of Gecko, atoms
-     * that are about to exit the parser must go through this method which
-     * reobtains dynamic atoms from the Gecko-global atom table.
-     *
-     * @param aAtom a potentially parser-scoped atom
-     * @return an nsIAtom that's pointer comparable on the main thread with
-     *         other not-parser atoms.
-     */
-    static inline already_AddRefed<nsIAtom> Reget(nsIAtom* aAtom)
-    {
-      if (!aAtom || aAtom->IsStaticAtom()) {
-        return dont_AddRef(aAtom);
-      }
-      nsAutoString str;
-      aAtom->ToString(str);
-      return do_GetAtom(str);
-    }
-
-    static nsresult AppendTextToTextNode(const char16_t* aBuffer,
-                                         uint32_t aLength,
-                                         nsIContent* aTextNode,
-                                         nsHtml5DocumentBuilder* aBuilder);
-
-    static nsresult AppendText(const char16_t* aBuffer,
-                               uint32_t aLength,
-                               nsIContent* aParent,
-                               nsHtml5DocumentBuilder* aBuilder);
-
-    static nsresult Append(nsIContent* aNode,
-                           nsIContent* aParent,
-                           nsHtml5DocumentBuilder* aBuilder);
-
-    static nsresult AppendToDocument(nsIContent* aNode,
-                                     nsHtml5DocumentBuilder* aBuilder);
-
-    static void Detach(nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder);
-
-    static nsresult AppendChildrenToNewParent(nsIContent* aNode,
-                                              nsIContent* aParent,
-                                              nsHtml5DocumentBuilder* aBuilder);
-
-    static nsresult FosterParent(nsIContent* aNode,
-                                 nsIContent* aParent,
-                                 nsIContent* aTable,
-                                 nsHtml5DocumentBuilder* aBuilder);
-
-    static nsresult AddAttributes(nsIContent* aNode,
-                                  nsHtml5HtmlAttributes* aAttributes,
-                                  nsHtml5DocumentBuilder* aBuilder);
-
-    static nsIContent* CreateElement(int32_t aNs,
-                                     nsIAtom* aName,
-                                     nsHtml5HtmlAttributes* aAttributes,
-                                     mozilla::dom::FromParser aFromParser,
-                                     nsHtml5DocumentBuilder* aBuilder);
-
-    static void SetFormElement(nsIContent* aNode, nsIContent* aParent);
-
-    static nsresult AppendIsindexPrompt(nsIContent* parent,
-                                        nsHtml5DocumentBuilder* aBuilder);
-
-    static nsresult FosterParentText(nsIContent* aStackParent,
-                                     char16_t* aBuffer,
-                                     uint32_t aLength,
-                                     nsIContent* aTable,
-                                     nsHtml5DocumentBuilder* aBuilder);
-
-    static nsresult AppendComment(nsIContent* aParent,
-                                  char16_t* aBuffer,
-                                  int32_t aLength,
-                                  nsHtml5DocumentBuilder* aBuilder);
-
-    static nsresult AppendCommentToDocument(char16_t* aBuffer,
-                                           int32_t aLength,
-                                           nsHtml5DocumentBuilder* aBuilder);
-
-    static nsresult AppendDoctypeToDocument(nsIAtom* aName,
-                                            const nsAString& aPublicId,
-                                            const nsAString& aSystemId,
-                                            nsHtml5DocumentBuilder* aBuilder);
-
-    static nsIContent* GetDocumentFragmentForTemplate(nsIContent* aNode);
-
-    static void PreventScriptExecution(nsIContent* aNode);
-
-    static void DoneAddingChildren(nsIContent* aNode,
-                                   nsHtml5DocumentBuilder* aBuilder);
-
-    static void DoneCreatingElement(nsIContent* aNode);
-
-    static void SvgLoad(nsIContent* aNode);
-
-    static void MarkMalformedIfScript(nsIContent* aNode);
-
     nsHtml5TreeOperation();
 
     ~nsHtml5TreeOperation();
 
-    inline void Init(eHtml5TreeOperation aOpCode)
-    {
+    inline void Init(eHtml5TreeOperation aOpCode) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       mOpCode = aOpCode;
     }
 
-    inline void Init(eHtml5TreeOperation aOpCode, nsIContentHandle* aNode)
-    {
+    inline void Init(eHtml5TreeOperation aOpCode, nsIContent** aNode) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aNode, "Initialized tree op with null node.");
       mOpCode = aOpCode;
-      mOne.node = static_cast<nsIContent**>(aNode);
+      mOne.node = aNode;
     }
 
     inline void Init(eHtml5TreeOperation aOpCode, 
-                     nsIContentHandle* aNode,
-                     nsIContentHandle* aParent)
-    {
+                     nsIContent** aNode,
+                     nsIContent** aParent) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aNode, "Initialized tree op with null node.");
       NS_PRECONDITION(aParent, "Initialized tree op with null parent.");
       mOpCode = aOpCode;
-      mOne.node = static_cast<nsIContent**>(aNode);
-      mTwo.node = static_cast<nsIContent**>(aParent);
+      mOne.node = aNode;
+      mTwo.node = aParent;
     }
     
     inline void Init(eHtml5TreeOperation aOpCode, 
                      const nsACString& aString,
-                     int32_t aInt32)
-    {
+                     int32_t aInt32) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
 
       int32_t len = aString.Length();
       char* str = new char[len + 1];
       const char* start = aString.BeginReading();
       for (int32_t i = 0; i < len; ++i) {
         str[i] = start[i];
@@ -242,247 +135,253 @@ class nsHtml5TreeOperation {
       mOpCode = aOpCode;
       mOne.charPtr = str;
       mFour.integer = aInt32;
     }
 
     inline void Init(eHtml5TreeOperation aOpCode,
                      const nsACString& aString,
                      int32_t aInt32,
-                     int32_t aLineNumber)
-    {
+                     int32_t aLineNumber) {
       Init(aOpCode, aString, aInt32);
       mTwo.integer = aLineNumber;
     }
 
     inline void Init(eHtml5TreeOperation aOpCode,
-                     nsIContentHandle* aNode,
-                     nsIContentHandle* aParent,
-                     nsIContentHandle* aTable)
-    {
+                     nsIContent** aNode,
+                     nsIContent** aParent, 
+                     nsIContent** aTable) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aNode, "Initialized tree op with null node.");
       NS_PRECONDITION(aParent, "Initialized tree op with null parent.");
       NS_PRECONDITION(aTable, "Initialized tree op with null table.");
       mOpCode = aOpCode;
-      mOne.node = static_cast<nsIContent**>(aNode);
-      mTwo.node = static_cast<nsIContent**>(aParent);
-      mThree.node = static_cast<nsIContent**>(aTable);
+      mOne.node = aNode;
+      mTwo.node = aParent;
+      mThree.node = aTable;
     }
 
-    inline void Init(nsHtml5DocumentMode aMode)
-    {
+    inline void Init(nsHtml5DocumentMode aMode) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       mOpCode = eTreeOpDocumentMode;
       mOne.mode = aMode;
     }
     
-    inline void InitScript(nsIContentHandle* aNode)
-    {
+    inline void InitScript(nsIContent** aNode) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aNode, "Initialized tree op with null node.");
       mOpCode = eTreeOpRunScript;
-      mOne.node = static_cast<nsIContent**>(aNode);
+      mOne.node = aNode;
       mTwo.state = nullptr;
     }
     
     inline void Init(int32_t aNamespace, 
                      nsIAtom* aName, 
                      nsHtml5HtmlAttributes* aAttributes,
-                     nsIContentHandle* aTarget,
-                     bool aFromNetwork)
-    {
+                     nsIContent** aTarget,
+                     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;
-      mOne.node = static_cast<nsIContent**>(aTarget);
+      mOne.node = aTarget;
       mTwo.atom = aName;
       if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
         mThree.attributes = nullptr;
       } else {
         mThree.attributes = aAttributes;
       }
     }
 
     inline void Init(eHtml5TreeOperation aOpCode, 
                      char16_t* aBuffer, 
                      int32_t aLength, 
-                     nsIContentHandle* aStackParent,
-                     nsIContentHandle* aTable)
-    {
+                     nsIContent** aStackParent,
+                     nsIContent** aTable) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
       mOpCode = aOpCode;
-      mOne.node = static_cast<nsIContent**>(aStackParent);
+      mOne.node = aStackParent;
       mTwo.unicharPtr = aBuffer;
-      mThree.node = static_cast<nsIContent**>(aTable);
+      mThree.node = aTable;
       mFour.integer = aLength;
     }
 
     inline void Init(eHtml5TreeOperation aOpCode, 
                      char16_t* aBuffer, 
                      int32_t aLength, 
-                     nsIContentHandle* aParent)
-    {
+                     nsIContent** aParent) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
       mOpCode = aOpCode;
-      mOne.node = static_cast<nsIContent**>(aParent);
+      mOne.node = aParent;
       mTwo.unicharPtr = aBuffer;
       mFour.integer = aLength;
     }
 
     inline void Init(eHtml5TreeOperation aOpCode, 
                      char16_t* aBuffer, 
-                     int32_t aLength)
-    {
+                     int32_t aLength) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
       mOpCode = aOpCode;
       mTwo.unicharPtr = aBuffer;
       mFour.integer = aLength;
     }
     
-    inline void Init(nsIContentHandle* aElement,
-                     nsHtml5HtmlAttributes* aAttributes)
-    {
+    inline void Init(nsIContent** aElement,
+                     nsHtml5HtmlAttributes* aAttributes) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aElement, "Initialized tree op with null element.");
       mOpCode = eTreeOpAddAttributes;
-      mOne.node = static_cast<nsIContent**>(aElement);
+      mOne.node = aElement;
       mTwo.attributes = aAttributes;
     }
     
     inline void Init(nsIAtom* aName, 
                      const nsAString& aPublicId, 
-                     const nsAString& aSystemId)
-    {
+                     const nsAString& aSystemId) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       mOpCode = eTreeOpAppendDoctypeToDocument;
       mOne.atom = aName;
       mTwo.stringPair = new nsHtml5TreeOperationStringPair(aPublicId, aSystemId);
     }
     
-    inline void Init(nsIContentHandle* aElement,
+    inline void Init(nsIContent** aElement,
                      const char* aMsgId,
                      nsIAtom* aAtom,
-                     nsIAtom* aOtherAtom)
-    {
+                     nsIAtom* aOtherAtom) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       mOpCode = eTreeOpAddError;
-      mOne.node = static_cast<nsIContent**>(aElement);
+      mOne.node = aElement;
       mTwo.charPtr = (char*)aMsgId;
       mThree.atom = aAtom;
       mFour.atom = aOtherAtom;
     }
 
-    inline void Init(nsIContentHandle* aElement,
+    inline void Init(nsIContent** aElement,
                      const char* aMsgId,
-                     nsIAtom* aAtom)
-    {
+                     nsIAtom* aAtom) {
       Init(aElement, aMsgId, aAtom, nullptr);
     }
 
-    inline void Init(nsIContentHandle* aElement,
-                     const char* aMsgId)
-    {
+    inline void Init(nsIContent** aElement,
+                     const char* aMsgId) {
       Init(aElement, aMsgId, nullptr, nullptr);
     }
 
     inline void Init(const char* aMsgId,
                      bool aError,
-                     int32_t aLineNumber)
-    {
+                     int32_t aLineNumber) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       mOpCode = eTreeOpMaybeComplainAboutCharset;
       mOne.charPtr = const_cast<char*>(aMsgId);
       mTwo.integer = aError;
       mThree.integer = aLineNumber;
     }
 
-    inline void Init(eHtml5TreeOperation aOpCode, const nsAString& aString)
-    {
+    inline void Init(eHtml5TreeOperation aOpCode, const nsAString& aString) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
 
       char16_t* str = NS_StringCloneData(aString);
       mOpCode = aOpCode;
       mOne.unicharPtr = str;
     }
     
     inline void Init(eHtml5TreeOperation aOpCode,
-                     nsIContentHandle* aNode,
-                     int32_t aInt)
-    {
+                     nsIContent** aNode,
+                     int32_t aInt) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aNode, "Initialized tree op with null node.");
       mOpCode = aOpCode;
-      mOne.node = static_cast<nsIContent**>(aNode);
+      mOne.node = aNode;
       mFour.integer = aInt;
     }
 
-    inline void InitAddClass(nsIContentHandle* aNode, const char16_t* aClass)
-    {
+    inline void InitAddClass(nsIContent** aNode, const char16_t* aClass) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aNode, "Initialized tree op with null node.");
       NS_PRECONDITION(aClass, "Initialized tree op with null string.");
       // aClass must be a literal string that does not need freeing
       mOpCode = eTreeOpAddClass;
-      mOne.node = static_cast<nsIContent**>(aNode);
+      mOne.node = aNode;
       mTwo.unicharPtr = (char16_t*)aClass;
     }
 
-    inline void InitAddLineNumberId(nsIContentHandle* aNode,
-                                    const int32_t aLineNumber)
-    {
+    inline void InitAddLineNumberId(nsIContent** aNode,
+                                    const int32_t aLineNumber) {
       NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
         "Op code must be uninitialized when initializing.");
       NS_PRECONDITION(aNode, "Initialized tree op with null node.");
       NS_PRECONDITION(aLineNumber > 0, "Initialized tree op with line number.");
       // aClass must be a literal string that does not need freeing
       mOpCode = eTreeOpAddLineNumberId;
-      mOne.node = static_cast<nsIContent**>(aNode);
+      mOne.node = aNode;
       mFour.integer = aLineNumber;
     }
 
-    inline bool IsRunScript()
-    {
+    inline bool IsRunScript() {
       return mOpCode == eTreeOpRunScript;
     }
     
-    inline void SetSnapshot(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine)
-    {
+    inline void SetSnapshot(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine) {
       NS_ASSERTION(IsRunScript(), 
         "Setting a snapshot for a tree operation other than eTreeOpRunScript!");
       NS_PRECONDITION(aSnapshot, "Initialized tree op with null snapshot.");
       mTwo.state = aSnapshot;
       mFour.integer = aLine;
     }
 
-    nsresult Perform(nsHtml5TreeOpExecutor* aBuilder,
-                     nsIContent** aScriptElement);
+    nsresult Perform(nsHtml5TreeOpExecutor* aBuilder, nsIContent** aScriptElement);
+
+    inline already_AddRefed<nsIAtom> Reget(nsIAtom* aAtom) {
+      if (!aAtom || aAtom->IsStaticAtom()) {
+        return dont_AddRef(aAtom);
+      }
+      nsAutoString str;
+      aAtom->ToString(str);
+      return do_GetAtom(str);
+    }
 
   private:
+
+    nsresult AppendTextToTextNode(const char16_t* aBuffer,
+                                  uint32_t aLength,
+                                  nsIContent* aTextNode,
+                                  nsHtml5TreeOpExecutor* aBuilder);
+
+    nsresult AppendText(const char16_t* aBuffer,
+                        uint32_t aLength,
+                        nsIContent* aParent,
+                        nsHtml5TreeOpExecutor* aBuilder);
+
+    nsresult Append(nsIContent* aNode,
+                    nsIContent* aParent,
+                    nsHtml5TreeOpExecutor* aBuilder);
+
+    nsresult AppendToDocument(nsIContent* aNode,
+                              nsHtml5TreeOpExecutor* aBuilder);
+  
     // possible optimization:
     // Make the queue take items the size of pointer and make the op code
     // decide how many operands it dequeues after it.
     eHtml5TreeOperation mOpCode;
     union {
       nsIContent**                    node;
       nsIAtom*                        atom;
       nsHtml5HtmlAttributes*          attributes;
--- a/parser/html/nsHtml5UTF16Buffer.cpp
+++ b/parser/html/nsHtml5UTF16Buffer.cpp
@@ -27,25 +27,24 @@
 
 #define nsHtml5UTF16Buffer_cpp__
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 #include "nsHtml5Tokenizer.h"
 #include "nsHtml5TreeBuilder.h"
 #include "nsHtml5MetaScanner.h"
 #include "nsHtml5AttributeName.h"
 #include "nsHtml5ElementName.h"
 #include "nsHtml5HtmlAttributes.h"
 #include "nsHtml5StackNode.h"
--- a/parser/html/nsHtml5UTF16Buffer.h
+++ b/parser/html/nsHtml5UTF16Buffer.h
@@ -28,25 +28,24 @@
 #ifndef nsHtml5UTF16Buffer_h
 #define nsHtml5UTF16Buffer_h
 
 #include "nsIAtom.h"
 #include "nsHtml5AtomTable.h"
 #include "nsString.h"
 #include "nsNameSpaceManager.h"
 #include "nsIContent.h"
-#include "nsTraceRefcnt.h"
+#include "nsISupportsImpl.h"
 #include "jArray.h"
 #include "nsHtml5ArrayCopy.h"
 #include "nsAHtml5TreeBuilderState.h"
 #include "nsHtml5Atoms.h"
 #include "nsHtml5ByteReadable.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsHtml5Macros.h"
-#include "nsIContentHandle.h"
 
 class nsHtml5StreamParser;
 
 class nsHtml5Tokenizer;
 class nsHtml5TreeBuilder;
 class nsHtml5MetaScanner;
 class nsHtml5AttributeName;
 class nsHtml5ElementName;
deleted file mode 100644
--- a/parser/html/nsIContentHandle.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-typedef void nsIContentHandle;