Backed out changeset 82c5f20d6ee2 (bug 1252211)
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 13 Jun 2017 12:20:16 +0200
changeset 412429 cc7f52437c99bc10b9cacca6b579e6aae6066ba7
parent 412428 54ce8da73fbb29ba56359808822af307e0a7ca41
child 412430 3936f4d38eaf56ab8cf9d40a2eca9e9dab33aee8
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1252211
milestone56.0a1
backs out82c5f20d6ee239c5e52b62440471c8a85ac6763f
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 changeset 82c5f20d6ee2 (bug 1252211)
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoID.h
dom/bindings/Bindings.conf
dom/tests/mochitest/general/test_interfaces.js
dom/webidl/LegacyQueryInterface.webidl
dom/webidl/TreeView.webidl
dom/webidl/XULElement.webidl
dom/webidl/XULTemplateBuilder.webidl
dom/webidl/moz.build
dom/xul/XULDocument.cpp
dom/xul/XULDocument.h
dom/xul/templates/moz.build
dom/xul/templates/nsIXULTemplateBuilder.idl
dom/xul/templates/nsTemplateMap.h
dom/xul/templates/nsTreeRows.h
dom/xul/templates/nsXULContentBuilder.cpp
dom/xul/templates/nsXULTemplateBuilder.cpp
dom/xul/templates/nsXULTemplateBuilder.h
dom/xul/templates/nsXULTemplateQueryProcessorRDF.cpp
dom/xul/templates/nsXULTemplateQueryProcessorStorage.cpp
dom/xul/templates/nsXULTreeBuilder.cpp
dom/xul/templates/nsXULTreeBuilder.h
layout/build/nsLayoutModule.cpp
layout/xul/tree/nsTreeColumns.h
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -71,16 +71,17 @@
 // CSS related includes
 #include "nsIDOMCSSRule.h"
 #include "nsMemory.h"
 
 // includes needed for the prototype chain interfaces
 #ifdef MOZ_XUL
 #include "nsITreeContentView.h"
 #include "nsITreeView.h"
+#include "nsIXULTemplateBuilder.h"
 #endif
 
 #include "nsIEventListenerService.h"
 #include "nsIMessageManager.h"
 
 #include "mozilla/dom/TouchEvent.h"
 
 #include "nsWrapperCacheInlines.h"
@@ -173,16 +174,21 @@ static nsDOMClassInfoData sClassInfoData
                            XPC_SCRIPTABLE_DONT_ENUM_QUERY_INTERFACE)
 
   // Misc Core related classes
 
   // XUL classes
 #ifdef MOZ_XUL
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(TreeContentView, nsDOMGenericSH,
                                       DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULTemplateBuilder, nsDOMGenericSH,
+                                      DEFAULT_SCRIPTABLE_FLAGS)
+
+  NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULTreeBuilder, nsDOMGenericSH,
+                                      DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentFrameMessageManager,
                                        nsMessageManagerSH<nsEventTargetSH>,
                                        DOM_DEFAULT_SCRIPTABLE_FLAGS |
                                        XPC_SCRIPTABLE_WANT_ENUMERATE |
                                        XPC_SCRIPTABLE_IS_GLOBAL_OBJECT)
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentProcessMessageManager,
@@ -448,16 +454,26 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
 #ifdef MOZ_XUL
   DOM_CLASSINFO_MAP_BEGIN(TreeContentView, nsITreeContentView)
     DOM_CLASSINFO_MAP_ENTRY(nsITreeContentView)
     DOM_CLASSINFO_MAP_ENTRY(nsITreeView)
   DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(XULTemplateBuilder, nsIXULTemplateBuilder)
+    DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(XULTreeBuilder, nsIXULTreeBuilder)
+    DOM_CLASSINFO_MAP_ENTRY(nsIXULTreeBuilder)
+    DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder)
+    DOM_CLASSINFO_MAP_ENTRY(nsITreeView)
+  DOM_CLASSINFO_MAP_END
 #endif
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentFrameMessageManager, nsISupports)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
     DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
     DOM_CLASSINFO_MAP_ENTRY(nsISyncMessageSender)
     DOM_CLASSINFO_MAP_ENTRY(nsIContentFrameMessageManager)
--- a/dom/base/nsDOMClassInfoID.h
+++ b/dom/base/nsDOMClassInfoID.h
@@ -19,16 +19,21 @@ enum nsDOMClassInfoID
   eDOMClassInfo_DOMPrototype_id,
   eDOMClassInfo_DOMConstructor_id,
 
   // XUL classes
 #ifdef MOZ_XUL
   eDOMClassInfo_TreeContentView_id,
 #endif
 
+#ifdef MOZ_XUL
+  eDOMClassInfo_XULTemplateBuilder_id,
+  eDOMClassInfo_XULTreeBuilder_id,
+#endif
+
   eDOMClassInfo_ContentFrameMessageManager_id,
   eDOMClassInfo_ContentProcessMessageManager_id,
   eDOMClassInfo_ChromeMessageBroadcaster_id,
   eDOMClassInfo_ChromeMessageSender_id,
 
   eDOMClassInfo_XULControlElement_id,
   eDOMClassInfo_XULLabeledControlElement_id,
   eDOMClassInfo_XULButtonElement_id,
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1428,24 +1428,16 @@ DOMInterfaces = {
 'XULDocument': {
     'headerFile': 'XULDocument.h'
 },
 
 'XULElement': {
     'nativeType': 'nsXULElement',
 },
 
-'XULTemplateBuilder': {
-    'nativeType': 'nsXULTemplateBuilder',
-},
-
-'XULTreeBuilder': {
-    'nativeType': 'nsXULTreeBuilder',
-},
-
 ####################################
 # Test Interfaces of various sorts #
 ####################################
 
 'TestInterface' : {
         # Keep this in sync with TestExampleInterface
         'headerFile': 'TestBindingHeader.h',
         'register': False,
@@ -1742,40 +1734,35 @@ addExternalIface('XULControllers', nativ
 addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True)
 addExternalIface('MozObserver', nativeType='nsIObserver', notflattened=True)
 addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource',
                  notflattened=True)
 addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True)
 addExternalIface('MozTreeView', nativeType='nsITreeView',
                   headerFile='nsITreeView.h', notflattened=True)
 addExternalIface('MozWakeLockListener', headerFile='nsIDOMWakeLockListener.h')
+addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder')
 addExternalIface('nsIBrowserDOMWindow', nativeType='nsIBrowserDOMWindow',
                  notflattened=True)
 addExternalIface('nsIDOMCrypto', nativeType='nsIDOMCrypto',
                  headerFile='Crypto.h')
 addExternalIface('nsIFile', nativeType='nsIFile', notflattened=True)
 addExternalIface('nsILoadGroup', nativeType='nsILoadGroup',
                  headerFile='nsILoadGroup.h', notflattened=True)
 addExternalIface('nsIMessageBroadcaster', nativeType='nsIMessageBroadcaster',
                  headerFile='nsIMessageManager.h', notflattened=True)
 addExternalIface('nsISelectionListener', nativeType='nsISelectionListener')
 addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
 addExternalIface('nsITransportProvider', nativeType='nsITransportProvider')
-addExternalIface('nsITreeSelection', nativeType='nsITreeSelection',
-                 notflattened=True)
 addExternalIface('nsISupports', nativeType='nsISupports')
 addExternalIface('nsIDocShell', nativeType='nsIDocShell', notflattened=True)
 addExternalIface('nsIEditor', nativeType='nsIEditor', notflattened=True)
 addExternalIface('nsIVariant', nativeType='nsIVariant', notflattened=True)
 addExternalIface('nsIScriptableRegion', nativeType='nsIScriptableRegion', notflattened=True)
 addExternalIface('OutputStream', nativeType='nsIOutputStream',
                  notflattened=True)
 addExternalIface('Principal', nativeType='nsIPrincipal',
                  headerFile='nsIPrincipal.h', notflattened=True)
 addExternalIface('StackFrame', nativeType='nsIStackFrame',
                  headerFile='nsIException.h', notflattened=True)
 addExternalIface('URI', nativeType='nsIURI', headerFile='nsIURI.h',
                  notflattened=True)
 addExternalIface('XULCommandDispatcher', notflattened=True)
-addExternalIface('XULTemplateResult', nativeType='nsIXULTemplateResult',
-                 notflattened=True)
-addExternalIface('XULTemplateRuleFilter', nativeType='nsIXULTemplateRuleFilter',
-                 notflattened=True)
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -1280,18 +1280,16 @@ var interfaceNamesInGlobalScope =
     {name: "XULLabeledControlElement", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULPopupElement", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULTemplateBuilder", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "XULTreeBuilder", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "XULTreeBuilderObserver", xbl: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer!
 
 function createInterfaceMap(isXBLScope) {
   var version = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
   var isNightly = version.endsWith("a1");
   var isRelease = !version.includes("a");
   var isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
--- a/dom/webidl/LegacyQueryInterface.webidl
+++ b/dom/webidl/LegacyQueryInterface.webidl
@@ -85,9 +85,8 @@ TreeColumns implements LegacyQueryInterf
 TreeWalker implements LegacyQueryInterface;
 ValidityState implements LegacyQueryInterface;
 WebSocket implements LegacyQueryInterface;
 Window implements LegacyQueryInterface;
 XMLHttpRequest implements LegacyQueryInterface;
 XMLHttpRequestUpload implements LegacyQueryInterface;
 XMLSerializer implements LegacyQueryInterface;
 XPathEvaluator implements LegacyQueryInterface;
-XULTemplateBuilder implements LegacyQueryInterface;
deleted file mode 100644
--- a/dom/webidl/TreeView.webidl
+++ /dev/null
@@ -1,222 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/. */
-
-interface nsITreeSelection;
-
-[NoInterfaceObject]
-interface TreeView
-{
-  /**
-   * The total number of rows in the tree (including the offscreen rows).
-   */
-  readonly attribute long rowCount;
-
-  /**
-   * The selection for this view.
-   */
-  [SetterThrows]
-  attribute nsITreeSelection? selection;
-
-  /** 
-   * A whitespace delimited list of properties.  For each property X the view
-   * gives back will cause the pseudoclasses  ::-moz-tree-cell(x),
-   * ::-moz-tree-row(x), ::-moz-tree-twisty(x), ::-moz-tree-image(x),
-   * ::-moz-tree-cell-text(x).  to be matched on the pseudoelement
-   * ::moz-tree-row.
-   */
-  [Throws]
-  DOMString getRowProperties(long row);
-
-  /**
-   * A whitespace delimited list of properties for a given cell.  Each
-   * property, x, that the view gives back will cause the pseudoclasses
-   *  ::-moz-tree-cell(x), ::-moz-tree-row(x), ::-moz-tree-twisty(x),
-   *  ::-moz-tree-image(x), ::-moz-tree-cell-text(x). to be matched on the
-   *  cell.
-   */
-  [Throws]
-  DOMString getCellProperties(long row, TreeColumn column);
-  
-  /**
-   * Called to get properties to paint a column background.  For shading the sort
-   * column, etc.
-   */
-  DOMString getColumnProperties(TreeColumn column);
-
-  /**
-   * Methods that can be used to test whether or not a twisty should be drawn,
-   * and if so, whether an open or closed twisty should be used.
-   */
-  [Throws]
-  boolean isContainer(long row);
-  [Throws]
-  boolean isContainerOpen(long row);
-  [Throws]
-  boolean isContainerEmpty(long row);
- 
-  /**
-   * isSeparator is used to determine if the row is a separator.
-   * A value of true will result in the tree drawing a horizontal separator.
-   * The tree uses the ::moz-tree-separator pseudoclass to draw the separator.
-   */
-  [Throws]
-  boolean isSeparator(long row);
-
-  /**
-   * Specifies if there is currently a sort on any column. Used mostly by dragdrop
-   * to affect drop feedback.
-   */
-  boolean isSorted();
-  
-  const short DROP_BEFORE = -1;
-  const short DROP_ON = 0;
-  const short DROP_AFTER = 1;
-  /**
-   * Methods used by the drag feedback code to determine if a drag is allowable at
-   * the current location. To get the behavior where drops are only allowed on
-   * items, such as the mailNews folder pane, always return false when
-   * the orientation is not DROP_ON.
-   */
-  [Throws]
-  boolean canDrop(long row, long orientation, DataTransfer? dataTransfer);
-
-  /**
-   * Called when the user drops something on this view. The |orientation| param
-   * specifies before/on/after the given |row|.
-   */
-  [Throws]
-  void drop(long row, long orientation, DataTransfer? dataTransfer);
-
-  /**
-   * Methods used by the tree to draw thread lines in the tree.
-   * getParentIndex is used to obtain the index of a parent row.
-   * If there is no parent row, getParentIndex returns -1.
-   */
-  [Throws]
-  long getParentIndex(long row);
-
-  /**
-   * hasNextSibling is used to determine if the row at rowIndex has a nextSibling
-   * that occurs *after* the index specified by afterIndex.  Code that is forced
-   * to march down the view looking at levels can optimize the march by starting
-   * at afterIndex+1.
-   */
-  [Throws]
-  boolean hasNextSibling(long row, long afterIndex);
-
-  /**
-   * The level is an integer value that represents
-   * the level of indentation.  It is multiplied by the width specified in the 
-   * :moz-tree-indentation pseudoelement to compute the exact indendation.
-   */
-  [Throws]
-  long getLevel(long row);
-
-  /**
-   * The image path for a given cell. For defining an icon for a cell.
-   * If the empty string is returned, the :moz-tree-image pseudoelement
-   * will be used.
-   */
-  [Throws]
-  DOMString getImageSrc(long row, TreeColumn column);
-
-  /**
-   * The progress mode for a given cell. This method is only called for
-   * columns of type |progressmeter|.
-   */
-  const short PROGRESS_NORMAL = 1;
-  const short PROGRESS_UNDETERMINED = 2;
-  const short PROGRESS_NONE = 3;
-  [Throws]
-  long getProgressMode(long row, TreeColumn column);
-
-  /**
-   * The value for a given cell. This method is only called for columns
-   * of type other than |text|.
-   */
-  [Throws]
-  DOMString getCellValue(long row, TreeColumn column);
-
-  /**
-   * The text for a given cell.  If a column consists only of an image, then
-   * the empty string is returned.  
-   */
-  [Throws]
-  DOMString getCellText(long row, TreeColumn column);
-
-  /**
-   * Called during initialization to link the view to the front end box object.
-   */
-  [Throws]
-  void setTree(TreeBoxObject? tree);
-  
-  /**
-   * Called on the view when an item is opened or closed.
-   */
-  [Throws]
-  void toggleOpenState(long row);
-
-  /**
-   * Called on the view when a header is clicked.
-   */
-  [Throws]
-  void cycleHeader(TreeColumn column);
-
-  /**
-   * Should be called from a XUL onselect handler whenever the selection changes.
-   */
-  void selectionChanged();
-
-  /**
-   * Called on the view when a cell in a non-selectable cycling column (e.g., unread/flag/etc.) is clicked.
-   */
-  void cycleCell(long row, TreeColumn column);
-  
-  /**
-   * isEditable is called to ask the view if the cell contents are editable.
-   * A value of true will result in the tree popping up a text field when 
-   * the user tries to inline edit the cell.
-   */
-  [Throws]
-  boolean isEditable(long row, TreeColumn column);
-
-  /**
-   * isSelectable is called to ask the view if the cell is selectable.
-   * This method is only called if the selection style is |cell| or |text|.
-   * XXXvarga shouldn't this be called isCellSelectable?
-   */
-  [Throws]
-  boolean isSelectable(long row, TreeColumn column);
-
-  /**
-   * setCellValue is called when the value of the cell has been set by the user.
-   * This method is only called for columns of type other than |text|.
-   */
-  [Throws]
-  void setCellValue(long row, TreeColumn column, DOMString value);
-
-  /**
-   * setCellText is called when the contents of the cell have been edited by the user.
-   */   
-  [Throws]
-  void setCellText(long row, TreeColumn column, DOMString value);
-
-  /**
-   * A command API that can be used to invoke commands on the selection.  The tree
-   * will automatically invoke this method when certain keys are pressed.  For example,
-   * when the DEL key is pressed, performAction will be called with the "delete" string.
-   */
-  void performAction(DOMString action);
-
-  /**
-   * A command API that can be used to invoke commands on a specific row.
-   */
-  void performActionOnRow(DOMString action, long row);
-
-  /**
-   * A command API that can be used to invoke commands on a specific cell.
-   */
-  void performActionOnCell(DOMString action, long row, TreeColumn column);
-};
--- a/dom/webidl/XULElement.webidl
+++ b/dom/webidl/XULElement.webidl
@@ -3,16 +3,17 @@
  * 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/.
  */
 
 interface XULControllers;
 interface MozFrameLoader;
 interface MozRDFCompositeDataSource;
 interface MozRDFResource;
+interface MozXULTemplateBuilder;
 
 [Func="IsChromeOrXBL"]
 interface XULElement : Element {
   // Layout properties
   [SetterThrows]
   attribute DOMString align;
   [SetterThrows]
   attribute DOMString dir;
@@ -79,17 +80,17 @@ interface XULElement : Element {
   [SetterThrows]
   attribute DOMString tooltipText;
   [SetterThrows]
   attribute DOMString statusText;
 
   attribute boolean allowEvents;
 
   readonly attribute MozRDFCompositeDataSource? database;
-  readonly attribute XULTemplateBuilder?        builder;
+  readonly attribute MozXULTemplateBuilder?     builder;
   [Throws]
   readonly attribute MozRDFResource?            resource;
   [Throws, ChromeOnly]
   readonly attribute XULControllers             controllers;
   [Throws]
   readonly attribute BoxObject?                 boxObject;
 
   [Throws]
deleted file mode 100644
--- a/dom/webidl/XULTemplateBuilder.webidl
+++ /dev/null
@@ -1,398 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* 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/. */
-
-interface MozRDFCompositeDataSource;
-interface MozRDFResource;
-interface nsISupports;
-interface XULTemplateResult;
-interface XULTemplateRuleFilter;
-
-callback interface XULBuilderListener
-{
-    void willRebuild(XULTemplateBuilder aBuilder);
-    void didRebuild(XULTemplateBuilder aBuilder);
-};
-
-/**
- * A template builder, given an input source of data, a template, and a
- * reference point, generates a list of results from the input, and copies
- * part of the template for each result. Templates may generate content
- * recursively, using the same template, but with the previous iteration's
- * results as the reference point. As an example, for an XML datasource the
- * initial reference point would be a specific node in the DOM tree and a
- * template might generate a list of all child nodes. For the next iteration,
- * those children would be used to generate output for their child nodes and
- * so forth.
- *
- * A template builder is attached to a single DOM node; this node is called
- * the root node and is expected to contain a XUL template element as a direct
- * child. Different template builders may be specialized in the manner in
- * which they generate and display the resulting content from the template.
- *
- * The structure of a template is as follows:
- *
- * <rootnode datasources="" ref="">
- *   <template>
- *     <queryset>
- *       <query>
- *       </query>
- *       <rule>
- *         <conditions>...</conditions>
- *         <bindings>...</bindings>
- *         <action>...</action>
- *       </rule>
- *     </queryset>
- *   </template>
- * </rootnode>
- *
- * The datasources attribute on the root node is used to identify the source
- * of data to be used. The ref attribute is used to specify the reference
- * point for the query. Currently, the datasource will either be an
- * nsIRDFDataSource or a DOM node. In the future, other datasource types may
- * be used.
- *
- * The <queryset> element contains a single query and one or more <rule>
- * elements. There may be more than one <queryset> if multiple queries are
- * desired, and this element is optional if only one query is needed -- in
- * that case the <query> and <rule>s are allowed to be children of the
- * <template> node
- *
- * The contents of the query are processed by a separate component called a
- * query processor. This query processor is expected to use this query to
- * generate results when asked by the template builder. The template builder
- * then generates output for each result based on the <rule> elements.
- *
- * This allows the query processor to be specific to a particular kind of
- * input data or query syntax, while the template builder remains independent
- * of the kind of data being used. Due to this, the query processor will be
- * supplied with the datasource and query which the template builder handles
- * in an opaque way, while the query processor handles these more
- * specifically.
- *
- * Results implement the nsIXULTemplateResult interface and may be identified
- * by an id which must be unique within a given set of query results.
- *
- * Each query may be accompanied by one or more <rule> elements. These rules
- * are evaluated by the template builder for each result produced by the
- * query. A rule consists of conditions that cause a rule to be either
- * accepted or rejected. The condition syntax allows for common conditional
- * handling; additional filtering may be applied by adding a custom filter
- * to a rule with the builder's addRuleFilter method.
- *
- * If a result passes a rule's conditions, this is considered a match, and the
- * content within the rule's <action> body is inserted as a sibling of the
- * <template>, assuming the template builder creates real DOM content. Only
- * one rule will match a result. For a tree builder, for example, the content
- * within the action body is used to create the tree rows instead. A matching
- * result must have its ruleMatched method called. When a result no longer
- * matches, the result's hasBeenRemoved method must be called.
- *
- * Optionally, the rule may have a <bindings> section which may be used to
- * define additional variables to be used within an action body. Each of these
- * declared bindings must be supplied to the query processor via its
- * addBinding method. The bindings are evaluated after a rule has matched.
- *
- * Templates may generate content recursively, using the previous iteration's
- * results as reference point to invoke the same queries. Since the reference
- * point is different, different output will typically be generated.
- *
- * The reference point nsIXULTemplateResult object for the first iteration is
- * determined by calling the query processor's translateRef method using the
- * value of the root node's ref attribute. This object may be retrieved later
- * via the builder's rootResult property.
- *
- * For convenience, each reference point as well as all results implement the
- * nsIXULTemplateResult interface, allowing the result objects from each
- * iteration to be used directly as the reference points for the next
- * iteration.
- *
- * When using multiple queries, each may generate results with the same id.
- * More than one of these results may match one of the rules in their
- * respective queries, however only the result for the earliest matching query
- * in the template becomes the active match and generates output. The
- * addResult, removeResult, replaceResult and resultBindingChanged methods may
- * be called by the query processor to indicate that the set of valid results
- * has changed, such that a different query may match. If a different match
- * would become active, the content for the existing match is removed and the
- * content for the new match is generated. A query processor is not required
- * to provide any support for updating results after they have been generated.
- *
- * See http://wiki.mozilla.org/XUL:Templates_Plan for details about templates.
- */
-[Func="IsChromeOrXBL"]
-interface XULTemplateBuilder
-{
-    /**
-     * The root node in the DOM to which this builder is attached.
-     */
-    readonly attribute Element? root;
-
-    /**
-     * The opaque datasource object that is used for the template. This object
-     * is created by the getDataSource method of the query processor. May be
-     * null if the datasource has not been loaded yet. Set this attribute to
-     * use a different datasource and rebuild the template.
-     *
-     * For an RDF datasource, this will be the same as the database. For XML
-     * this will be the nsIDOMNode for the datasource document or node for
-     * an inline reference (such as #name). Other query processors may use
-     * other types for the datasource.
-     */
-    [SetterThrows]
-    attribute nsISupports? datasource;
-
-    /**
-     * The composite datasource that the template builder observes
-     * and uses to create content. This is used only for RDF queries and is
-     * maintained for backwards compatibility. It will be the same object as
-     * the datasource property. For non-RDF queries, it will always be null.
-     */
-    readonly attribute MozRDFCompositeDataSource? database;
-
-    /**
-     * The virtual result representing the starting reference point,
-     * determined by calling the query processor's translateRef method
-     * with the root node's ref attribute as an argument.
-     */
-    readonly attribute XULTemplateResult? rootResult;
-
-    /**
-     * Force the template builder to rebuild its content. All existing content
-     * will be removed first. The query processor's done() method will be
-     * invoked during cleanup, followed by its initializeForBuilding method
-     * when the content is to be regenerated.
-     * 
-     */
-    [Throws]
-    void rebuild();
-
-    /**
-     * Reload any of our RDF datasources that support nsIRDFRemoteDatasource. 
-     *
-     * @note This is a temporary hack so that remote-XUL authors can
-     *       reload remote datasources. When RDF becomes remote-scriptable,
-     *       this will no longer be necessary.
-     */
-    [Throws]
-    void refresh();
-
-    /**
-     * Inform the template builder that a new result is available. The builder
-     * will add this result to the set of results. The query node that the
-     * new result applies to must be specified using the aQueryNode parameter.
-     *
-     * The builder will apply the rules associated with the query to the new
-     * result, unless a result with the same id from an earlier query
-     * supersedes it, and the result's RuleMatched method will be called if it
-     * matches.
-     *
-     * @param aResult the result to add
-     * @param aQueryNode the query that the result applies to
-     */
-    [Throws]
-    void addResult(XULTemplateResult aResult, Node aQueryNode);
-
-    /**
-     * Inform the template builder that a result no longer applies. The builder
-     * will call the remove content generated for the result, if any. If a
-     * different query would then match instead, it will become the active
-     * match. This method will have no effect if the result isn't known to the
-     * builder.
-     *
-     * @param aResult the result to remove
-     *
-     * @throws NS_ERROR_NULL_POINTER if aResult is null
-     */
-    [Throws]
-    void removeResult(XULTemplateResult aResult);
-
-    /**
-     * Inform the template builder that one result should be replaced with
-     * another. Both the old result (aOldResult) and the new result
-     * (aNewResult) must have the same id. The query node that the new result
-     * applies to must be specified using the aQueryNode parameter.
-     *
-     * This method is expected to have the same effect as calling both
-     * removeResult for the old result and addResult for the new result.
-     *
-     * @param aOldResult the old result
-     * @param aNewResult the new result
-     * @param aQueryNode the query that the new result applies to
-     *
-     * @throws NS_ERROR_NULL_POINTER if either argument is null, or
-     *         NS_ERROR_INVALID_ARG if the ids don't match
-     */
-    [Throws]
-    void replaceResult(XULTemplateResult aOldResult,
-                       XULTemplateResult aNewResult,
-                       Node aQueryNode);
-
-    /**
-     * Inform the template builder that one or more of the optional bindings
-     * for a result has changed. In this case, the rules are not reapplied as
-     * it is expected that the same rule will still apply. The builder will
-     * resynchronize any variables that are referenced in the action body.
-     *
-     * @param aResult the result to change
-     *
-     * @throws NS_ERROR_NULL_POINTER if aResult is null
-     */
-    [Throws]
-    void resultBindingChanged(XULTemplateResult aResult);
-
-    /**
-     * Return the result for a given id. Only one such result is returned and
-     * is always the result with that id associated with the active match.
-     * This method will return null is there is no result for the id.
-     *
-     * @param aId the id to return the result for
-     */
-    [Throws]
-    XULTemplateResult? getResultForId(DOMString aId);
-
-    /**
-     * Retrieve the result corresponding to a generated element, or null is
-     * there isn't one.
-     *
-     * @param aContent element to result the result of
-     */
-    XULTemplateResult? getResultForContent(Element aElement);
-
-    /**
-     * Returns true if the node has content generated for it. This method is
-     * intended to be called only by the RDF query processor. If aTag is set,
-     * the content must have a tag name that matches aTag. aTag may be ignored
-     * for builders that don't generate real DOM content.
-     *
-     * @param aNode node to check
-     * @param aTag tag that must match
-     */
-    [Throws]
-    boolean hasGeneratedContent(MozRDFResource aNode, DOMString? aTag);
-
-    /**
-     * Adds a rule filter for a given rule, which may be used for specialized
-     * rule filtering. Any existing filter on the rule is removed. The default
-     * conditions specified inside the <rule> tag are applied before the
-     * rule filter is applied, meaning that the filter may be used to further
-     * filter out results but not reaccept results that have already been
-     * rejected.
-     *
-     * @param aRule the rule to apply the filter to
-     * @param aFilter the filter to add
-     */
-    [Throws]
-    void addRuleFilter(Node aRule, XULTemplateRuleFilter aFilter);
-
-    /**
-     * Add a listener to this template builder. The template builder
-     * holds a strong reference to the listener.
-     */
-    void addListener(XULBuilderListener aListener);
-
-    /**
-     * Remove a listener from this template builder.
-     */
-    void removeListener(XULBuilderListener aListener);
-};
-
-/**
- *  XULTreeBuilderObserver
- *  This interface allows clients of the XULTreeBuilder to define domain 
- *  specific handling of specific nsITreeView methods that 
- *  XULTreeBuilder does not implement.
- */
-[Func="IsChromeOrXBL"]
-callback interface XULTreeBuilderObserver
-{
-    const long DROP_BEFORE = -1;
-    const long DROP_ON = 0;
-    const long DROP_AFTER = 1;
-    /**
-     * Methods used by the drag feedback code to determine if a drag is
-     * allowable at the current location. To get the behavior where drops are
-     * only allowed on items, such as the mailNews folder pane, always return
-     * false when the orientation is not DROP_ON.
-     */
-    boolean canDrop(long index, long orientation, DataTransfer? dataTransfer);
-
-    /**
-     * Called when the user drops something on this view. The |orientation|
-     * param specifies before/on/after the given |row|.
-     */
-    void onDrop(long row, long orientation, DataTransfer? dataTransfer);
- 
-    /** 
-     * Called when an item is opened or closed. 
-     */
-    void onToggleOpenState(long index);
-
-    /** 
-	 * Called when a header is clicked.
-     */
-    void onCycleHeader(DOMString colID, Element? elt);
-
-    /**
-     * Called when a cell in a non-selectable cycling column (e.g. 
-     * unread/flag/etc.) is clicked.
-     */
-    void onCycleCell(long row, DOMString colID);
-
-    /** 
-     * Called when selection in the tree changes
-     */
-    void onSelectionChanged();
-
-    /**
-     * A command API that can be used to invoke commands on the selection.  
-     * The tree will automatically invoke this method when certain keys 
-     * are pressed.  For example, when the DEL key is pressed, performAction 
-     * will be called with the "delete" string. 
-     */
-    void onPerformAction(DOMString action);
-
-    /**
-     * A command API that can be used to invoke commands on a specific row.
-     */
-    void onPerformActionOnRow(DOMString action, long row);
-
-    /**
-     * A command API that can be used to invoke commands on a specific cell.
-     */
-    void onPerformActionOnCell(DOMString action, long row, DOMString colID);
-};
-
-[Func="IsChromeOrXBL"]
-interface XULTreeBuilder : XULTemplateBuilder
-{
-    /**
-     * Retrieve the RDF resource associated with the specified row.
-     */
-    [Throws]
-    MozRDFResource? getResourceAtIndex(long aRowIndex);
-
-    /**
-     * Retrieve the index associated with specified RDF resource.
-     */
-    [Throws]
-    long getIndexOfResource(MozRDFResource resource);
-
-    /** 
-     * Add a Tree Builder Observer to handle Tree View 
-     * methods that the base builder does not implement. 
-     */
-    void addObserver(XULTreeBuilderObserver aObserver);
-
-    /** 
-     * Remove an Tree Builder Observer.
-     */
-    void removeObserver(XULTreeBuilderObserver aObserver);
-
-    /** 
-     * Sort the contents of the tree using the specified column.
-     */
-    void sort(Element aColumnElement);
-};
-XULTreeBuilder implements TreeView;
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -921,17 +921,16 @@ WEBIDL_FILES = [
     'TimeRanges.webidl',
     'Touch.webidl',
     'TouchEvent.webidl',
     'TouchList.webidl',
     'TransitionEvent.webidl',
     'TreeBoxObject.webidl',
     'TreeColumn.webidl',
     'TreeColumns.webidl',
-    'TreeView.webidl',
     'TreeWalker.webidl',
     'U2F.webidl',
     'UDPMessageEvent.webidl',
     'UDPSocket.webidl',
     'UIEvent.webidl',
     'URL.webidl',
     'URLSearchParams.webidl',
     'ValidityState.webidl',
@@ -973,17 +972,16 @@ WEBIDL_FILES = [
     'XPathEvaluator.webidl',
     'XPathExpression.webidl',
     'XPathNSResolver.webidl',
     'XPathResult.webidl',
     'XSLTProcessor.webidl',
     'XULCommandEvent.webidl',
     'XULDocument.webidl',
     'XULElement.webidl',
-    'XULTemplateBuilder.webidl',
 ]
 
 if CONFIG['MOZ_WEBRTC']:
     WEBIDL_FILES += [
         'DataChannel.webidl',
         'MediaStreamList.webidl',
         'PeerConnectionImpl.webidl',
         'PeerConnectionImplEnums.webidl',
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -91,18 +91,16 @@
 #include "nsTextNode.h"
 #include "nsJSUtils.h"
 #include "mozilla/dom/URL.h"
 #include "nsIContentPolicy.h"
 #include "mozAutoDocUpdate.h"
 #include "xpcpublic.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
-#include "nsXULTemplateBuilder.h"
-#include "nsXULTreeBuilder.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 //
 // CIDs
 //
@@ -3655,17 +3653,17 @@ XULDocument::CheckTemplateBuilderHookup(
     // Check aElement for a 'datasources' attribute, if it has
     // one a XUL template builder needs to be hooked up.
     *aNeedsHookup = aElement->HasAttr(kNameSpaceID_None,
                                       nsGkAtoms::datasources);
     return NS_OK;
 }
 
 /* static */ nsresult
-XULDocument::CreateTemplateBuilder(Element* aElement)
+XULDocument::CreateTemplateBuilder(nsIContent* aElement)
 {
     // Check if need to construct a tree builder or content builder.
     bool isTreeBuilder = false;
 
     // return successful if the element is not is a document, as an inline
     // script could have removed it
     nsIDocument* document = aElement->GetUncomposedDoc();
     NS_ENSURE_TRUE(document, NS_OK);
@@ -3684,19 +3682,23 @@ XULDocument::CreateTemplateBuilder(Eleme
         aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::flags, flags);
         if (flags.Find(NS_LITERAL_STRING("dont-build-content")) >= 0) {
             isTreeBuilder = true;
         }
     }
 
     if (isTreeBuilder) {
         // Create and initialize a tree builder.
-        RefPtr<nsXULTreeBuilder> builder = new nsXULTreeBuilder(aElement);
-        nsresult rv = builder->Init();
-        NS_ENSURE_SUCCESS(rv, rv);
+        nsCOMPtr<nsIXULTemplateBuilder> builder =
+            do_CreateInstance("@mozilla.org/xul/xul-tree-builder;1");
+
+        if (! builder)
+            return NS_ERROR_FAILURE;
+
+        builder->Init(aElement);
 
         // Create a <treechildren> if one isn't there already.
         // XXXvarga what about attributes?
         nsCOMPtr<nsIContent> bodyContent;
         nsXULContentUtils::FindChildByTag(aElement, kNameSpaceID_XUL,
                                           nsGkAtoms::treechildren,
                                           getter_AddRefs(bodyContent));
 
@@ -3705,20 +3707,23 @@ XULDocument::CreateTemplateBuilder(Eleme
                 document->CreateElem(nsDependentAtomString(nsGkAtoms::treechildren),
                                      nullptr, kNameSpaceID_XUL);
 
             aElement->AppendChildTo(bodyContent, false);
         }
     }
     else {
         // Create and initialize a content builder.
-        nsCOMPtr<nsIXULTemplateBuilder> builder;
-        nsresult rv = NS_NewXULContentBuilder(aElement, getter_AddRefs(builder));
-        NS_ENSURE_SUCCESS(rv, rv);
-
+        nsCOMPtr<nsIXULTemplateBuilder> builder
+            = do_CreateInstance("@mozilla.org/xul/xul-template-builder;1");
+
+        if (! builder)
+            return NS_ERROR_FAILURE;
+
+        builder->Init(aElement);
         builder->CreateContents(aElement, false);
     }
 
     return NS_OK;
 }
 
 
 nsresult
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -469,17 +469,17 @@ protected:
      */
     static nsresult
     CheckTemplateBuilderHookup(nsIContent* aElement, bool* aNeedsHookup);
 
     /**
      * Create a XUL template builder on the specified node.
      */
     static nsresult
-    CreateTemplateBuilder(Element* aElement);
+    CreateTemplateBuilder(nsIContent* aElement);
 
     /**
      * Add the current prototype's style sheets (currently it's just
      * style overlays from the chrome registry) to the document.
      */
     nsresult AddPrototypeSheets();
 
 
@@ -561,20 +561,20 @@ protected:
         virtual Result Resolve() override;
     };
 
     friend class OverlayForwardReference;
 
     class TemplateBuilderHookup : public nsForwardReference
     {
     protected:
-        nsCOMPtr<Element> mElement; // [OWNER]
+        nsCOMPtr<nsIContent> mElement; // [OWNER]
 
     public:
-        explicit TemplateBuilderHookup(Element* aElement)
+        explicit TemplateBuilderHookup(nsIContent* aElement)
             : mElement(aElement) {}
 
         virtual Phase GetPhase() override { return eHookup; }
         virtual Result Resolve() override;
     };
 
     friend class TemplateBuilderHookup;
 
--- a/dom/xul/templates/moz.build
+++ b/dom/xul/templates/moz.build
@@ -12,22 +12,16 @@ XPIDL_SOURCES += [
     'nsIXULTemplateBuilder.idl',
     'nsIXULTemplateQueryProcessor.idl',
     'nsIXULTemplateResult.idl',
     'nsIXULTemplateRuleFilter.idl',
 ]
 
 XPIDL_MODULE = 'xultmpl'
 
-EXPORTS += [
-    'nsTreeRows.h',
-    'nsXULTemplateBuilder.h',
-    'nsXULTreeBuilder.h',
-]
-
 UNIFIED_SOURCES += [
     'nsContentSupportMap.cpp',
     'nsContentTestNode.cpp',
     'nsInstantiationNode.cpp',
     'nsRDFBinding.cpp',
     'nsRDFConInstanceTestNode.cpp',
     'nsRDFConMemberTestNode.cpp',
     'nsRDFPropertyTestNode.cpp',
--- a/dom/xul/templates/nsIXULTemplateBuilder.idl
+++ b/dom/xul/templates/nsIXULTemplateBuilder.idl
@@ -278,16 +278,24 @@ interface nsIXULTemplateBuilder : nsISup
      * rejected.
      *
      * @param aRule the rule to apply the filter to
      * @param aFilter the filter to add
      */
     void addRuleFilter(in nsIDOMNode aRule, in nsIXULTemplateRuleFilter aFilter);
 
     /**
+     * Called to initialize a XUL content builder on a particular root
+     * element. This element presumably has a ``datasources''
+     * attribute, which the builder will parse to set up the template
+     * builder's datasources.
+     */
+    [noscript] void init(in nsIContent aElement);
+
+    /**
      * Invoked lazily by a XUL element that needs its child content built.
      * If aForceCreation is true, then the contents of an element will be
      * generated even if it is closed. If false, the element will only
      * generate its contents if it is open. This behaviour is used with menus.
      */
     [noscript] void createContents(in nsIContent aElement,
                                    in boolean aForceCreation);
 
--- a/dom/xul/templates/nsTemplateMap.h
+++ b/dom/xul/templates/nsTemplateMap.h
@@ -22,17 +22,17 @@ public:
     nsTemplateMap() : mTable(PLDHashTable::StubOps(), sizeof(Entry)) { }
 
     ~nsTemplateMap() { }
 
     void
     Put(nsIContent* aContent, nsIContent* aTemplate) {
         NS_ASSERTION(!mTable.Search(aContent), "aContent already in map");
 
-        auto entry = static_cast<Entry*>(mTable.Add(aContent, mozilla::fallible));
+        auto entry = static_cast<Entry*>(mTable.Add(aContent, fallible));
 
         if (entry) {
             entry->mContent = aContent;
             entry->mTemplate = aTemplate;
         }
     }
 
     void
--- a/dom/xul/templates/nsTreeRows.h
+++ b/dom/xul/templates/nsTreeRows.h
@@ -5,19 +5,19 @@
 
 #ifndef nsTreeRows_h__
 #define nsTreeRows_h__
 
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "PLDHashTable.h"
 #include "nsIXULTemplateResult.h"
+#include "nsTemplateMatch.h"
 #include "nsIRDFResource.h"
 
-class nsTemplateMatch;
 
 /**
  * This class maintains the state of the XUL tree builder's
  * rows. It maps a row number to the nsTemplateMatch object that
  * populates the row.
  */
 class nsTreeRows
 {
--- a/dom/xul/templates/nsXULContentBuilder.cpp
+++ b/dom/xul/templates/nsXULContentBuilder.cpp
@@ -69,33 +69,32 @@ using namespace mozilla::dom;
  * becomes the container to insert into.
  */
 class nsXULContentBuilder : public nsXULTemplateBuilder
 {
 public:
     // nsIXULTemplateBuilder interface
     NS_IMETHOD CreateContents(nsIContent* aElement, bool aForceCreation) override;
 
-    using nsIXULTemplateBuilder::HasGeneratedContent;
-    bool HasGeneratedContent(nsIRDFResource* aResource,
-                             const nsAString& aTag,
-                             ErrorResult& aError) override;
+    NS_IMETHOD HasGeneratedContent(nsIRDFResource* aResource,
+                                   nsIAtom* aTag,
+                                   bool* aGenerated) override;
 
-    using nsIXULTemplateBuilder::GetResultForContent;
-    nsIXULTemplateResult* GetResultForContent(Element& aElement) override;
+    NS_IMETHOD GetResultForContent(nsIDOMElement* aContent,
+                                   nsIXULTemplateResult** aResult) override;
 
     // nsIMutationObserver interface
     NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
     NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
 
 protected:
     friend nsresult
-    NS_NewXULContentBuilder(Element* aElement, nsIXULTemplateBuilder** aBuilder);
+    NS_NewXULContentBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
-    explicit nsXULContentBuilder(Element* aElement);
+    nsXULContentBuilder();
 
     void Traverse(nsCycleCollectionTraversalCallback& aCb) const override
     {
         mSortState.Traverse(aCb);
     }
 
     virtual void Uninit(bool aIsFinal) override;
 
@@ -336,28 +335,36 @@ protected:
 
     /**
      * Information about the currently active sort
      */
     nsSortState mSortState;
 };
 
 nsresult
-NS_NewXULContentBuilder(Element* aElement, nsIXULTemplateBuilder** aBuilder)
+NS_NewXULContentBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult)
 {
-    RefPtr<nsXULContentBuilder> builder = new nsXULContentBuilder(aElement);
-    nsresult rv = builder->Init();
-    NS_ENSURE_SUCCESS(rv, rv);
+    NS_PRECONDITION(aOuter == nullptr, "no aggregation");
+    if (aOuter)
+        return NS_ERROR_NO_AGGREGATION;
+
+    nsresult rv;
+    nsXULContentBuilder* result = new nsXULContentBuilder();
+    NS_ADDREF(result); // stabilize
 
-    builder.forget(aBuilder);
-    return NS_OK;
+    rv = result->InitGlobals();
+
+    if (NS_SUCCEEDED(rv))
+        rv = result->QueryInterface(aIID, aResult);
+
+    NS_RELEASE(result);
+    return rv;
 }
 
-nsXULContentBuilder::nsXULContentBuilder(Element* aElement)
-  : nsXULTemplateBuilder(aElement)
+nsXULContentBuilder::nsXULContentBuilder()
 {
   mSortState.initialized = false;
 }
 
 void
 nsXULContentBuilder::Uninit(bool aIsFinal)
 {
     if (! aIsFinal && mRoot) {
@@ -1406,81 +1413,93 @@ nsXULContentBuilder::CreateContents(nsIC
     // don't build contents for closed elements. aForceCreation will be true
     // when a menu is about to be opened, so the content should be built anyway.
     if (!aForceCreation && !IsOpen(aElement))
         return NS_OK;
 
     return CreateTemplateAndContainerContents(aElement, aForceCreation);
 }
 
-bool
+NS_IMETHODIMP
 nsXULContentBuilder::HasGeneratedContent(nsIRDFResource* aResource,
-                                         const nsAString& aTag,
-                                         ErrorResult& aError)
+                                         nsIAtom* aTag,
+                                         bool* aGenerated)
 {
-    if (!mRoot || !mRootResult) {
-        aError.Throw(NS_ERROR_NOT_INITIALIZED);
-        return false;
-    }
+    *aGenerated = false;
+    NS_ENSURE_TRUE(mRoot, NS_ERROR_NOT_INITIALIZED);
+    NS_ENSURE_STATE(mRootResult);
 
     nsCOMPtr<nsIRDFResource> rootresource;
-    aError = mRootResult->GetResource(getter_AddRefs(rootresource));
-    if (aError.Failed()) {
-        return false;
-    }
+    nsresult rv = mRootResult->GetResource(getter_AddRefs(rootresource));
+    if (NS_FAILED(rv))
+        return rv;
 
     // the root resource is always acceptable
     if (aResource == rootresource) {
-        return DOMStringIsNull(aTag) || mRoot->NodeInfo()->LocalName().Equals(aTag);
+        if (!aTag || mRoot->NodeInfo()->NameAtom() == aTag)
+            *aGenerated = true;
     }
+    else {
+        const char* uri;
+        aResource->GetValueConst(&uri);
 
-    const char* uri;
-    aResource->GetValueConst(&uri);
+        NS_ConvertUTF8toUTF16 refID(uri);
+
+        // just return if the node is no longer in a document
+        nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mRoot->GetComposedDoc());
+        if (! xuldoc)
+            return NS_OK;
+
+        nsCOMArray<nsIContent> elements;
+        xuldoc->GetElementsForID(refID, elements);
 
-    NS_ConvertUTF8toUTF16 refID(uri);
+        uint32_t cnt = elements.Count();
+
+        for (int32_t i = int32_t(cnt) - 1; i >= 0; --i) {
+            nsCOMPtr<nsIContent> content = elements.SafeObjectAt(i);
 
-    // just return if the node is no longer in a document
-    nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mRoot->GetComposedDoc());
-    if (!xuldoc) {
-        return false;
+            do {
+                nsTemplateMatch* match;
+                if (content == mRoot || mContentSupportMap.Get(content, &match)) {
+                    // If we've got a tag, check it to ensure we're consistent.
+                    if (!aTag || content->NodeInfo()->NameAtom() == aTag) {
+                        *aGenerated = true;
+                        return NS_OK;
+                    }
+                }
+
+                content = content->GetParent();
+            } while (content);
+        }
     }
 
-    nsCOMArray<nsIContent> elements;
-    xuldoc->GetElementsForID(refID, elements);
+    return NS_OK;
+}
 
-    uint32_t cnt = elements.Count();
-
-    for (int32_t i = int32_t(cnt) - 1; i >= 0; --i) {
-        nsCOMPtr<nsIContent> content = elements.SafeObjectAt(i);
+NS_IMETHODIMP
+nsXULContentBuilder::GetResultForContent(nsIDOMElement* aElement,
+                                         nsIXULTemplateResult** aResult)
+{
+    NS_ENSURE_ARG_POINTER(aElement);
+    NS_ENSURE_ARG_POINTER(aResult);
 
-        do {
-            nsTemplateMatch* match;
-            if (content == mRoot || mContentSupportMap.Get(content, &match)) {
-                // If we've got a tag, check it to ensure we're consistent.
-                if (DOMStringIsNull(aTag) || content->NodeInfo()->LocalName().Equals(aTag)) {
-                    return true;
-                }
-            }
-
-            content = content->GetParent();
-        } while (content);
+    nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
+    if (content == mRoot) {
+        *aResult = mRootResult;
+    }
+    else {
+        nsTemplateMatch *match = nullptr;
+        if (mContentSupportMap.Get(content, &match))
+            *aResult = match->mResult;
+        else
+            *aResult = nullptr;
     }
 
-    return false;
-}
-
-nsIXULTemplateResult*
-nsXULContentBuilder::GetResultForContent(Element& aElement)
-{
-    if (&aElement == mRoot) {
-        return mRootResult;
-    }
-
-    nsTemplateMatch* match;
-    return mContentSupportMap.Get(&aElement, &match) ? match->mResult.get() : nullptr;
+    NS_IF_ADDREF(*aResult);
+    return NS_OK;
 }
 
 //----------------------------------------------------------------------
 //
 // nsIDocumentObserver methods
 //
 
 void
--- a/dom/xul/templates/nsXULTemplateBuilder.cpp
+++ b/dom/xul/templates/nsXULTemplateBuilder.cpp
@@ -30,55 +30,51 @@
 #include "nsIDOMNodeList.h"
 #include "nsIObserverService.h"
 #include "nsIRDFCompositeDataSource.h"
 #include "nsIRDFInferDataSource.h"
 #include "nsIRDFContainerUtils.h"
 #include "nsIXULDocument.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsIXULBuilderListener.h"
-#include "nsIRDFCompositeDataSource.h"
 #include "nsIRDFRemoteDataSource.h"
 #include "nsIRDFService.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptGlobalObject.h"
-#include "nsIScriptSecurityManager.h"
 #include "nsIServiceManager.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIMutableArray.h"
 #include "nsIURL.h"
 #include "nsIXPConnect.h"
 #include "nsContentCID.h"
 #include "nsNameSpaceManager.h"
 #include "nsRDFCID.h"
 #include "nsXULContentUtils.h"
 #include "nsString.h"
 #include "nsTArray.h"
-#include "nsTemplateMatch.h"
-#include "nsTemplateRule.h"
 #include "nsXPIDLString.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsGkAtoms.h"
 #include "nsXULElement.h"
 #include "jsapi.h"
 #include "mozilla/Logging.h"
 #include "rdf.h"
 #include "PLDHashTable.h"
 #include "plhash.h"
+#include "nsDOMClassInfoID.h"
 #include "nsPIDOMWindow.h"
 #include "nsIConsoleService.h" 
 #include "nsNetUtil.h"
 #include "nsXULTemplateBuilder.h"
 #include "nsXULTemplateQueryProcessorRDF.h"
 #include "nsXULTemplateQueryProcessorXML.h"
 #include "nsXULTemplateQueryProcessorStorage.h"
 #include "nsContentUtils.h"
 #include "ChildIterator.h"
 #include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/XULTemplateBuilderBinding.h"
 #include "nsGlobalWindow.h"
 
 using namespace mozilla::dom;
 using namespace mozilla;
 
 //----------------------------------------------------------------------
 //
 // nsXULTemplateBuilder
@@ -95,19 +91,18 @@ LazyLogModule gXULTemplateLog("nsXULTemp
 
 #define NS_QUERY_PROCESSOR_CONTRACTID_PREFIX "@mozilla.org/xul/xul-query-processor;1?name="
 
 //----------------------------------------------------------------------
 //
 // nsXULTemplateBuilder methods
 //
 
-nsXULTemplateBuilder::nsXULTemplateBuilder(Element* aElement)
-    : mRoot(aElement),
-      mQueriesCompiled(false),
+nsXULTemplateBuilder::nsXULTemplateBuilder(void)
+    : mQueriesCompiled(false),
       mFlags(0),
       mTop(nullptr),
       mObservedDocument(nullptr)
 {
 }
 
 void
 nsXULTemplateBuilder::DestroyMatchMap()
@@ -226,17 +221,16 @@ nsXULTemplateBuilder::Uninit(bool aIsFin
     mMemberVariable = nullptr;
 
     mQueriesCompiled = false;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateBuilder)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateBuilder)
-    NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDataSource)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDB)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mCompDB)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootResult)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mListeners)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mQueryProcessor)
     tmp->DestroyMatchMap();
@@ -279,212 +273,167 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
         uint16_t j, rulesCount = set->RuleCount();
         for (j = 0; j < rulesCount; ++j) {
           set->GetRuleAt(j)->Traverse(cb);
         }
       }
     }
     tmp->Traverse(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsXULTemplateBuilder)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULTemplateBuilder)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULTemplateBuilder)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULTemplateBuilder)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIXULTemplateBuilder)
   NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULTemplateBuilder)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULTemplateBuilder)
 NS_INTERFACE_MAP_END
 
-JSObject* 
-nsXULTemplateBuilder::WrapObject(JSContext* aCx,
-                                 JS::Handle<JSObject*> aGivenProto)
-{
-    return XULTemplateBuilderBinding::Wrap(aCx, this, aGivenProto);
-}
-
 //----------------------------------------------------------------------
 //
 // nsIXULTemplateBuilder methods
 //
 
 NS_IMETHODIMP
 nsXULTemplateBuilder::GetRoot(nsIDOMElement** aResult)
 {
-    nsCOMPtr<nsIDOMElement> result = do_QueryInterface(GetRoot());
-    result.forget(aResult);
+    if (mRoot) {
+        return CallQueryInterface(mRoot, aResult);
+    }
+    *aResult = nullptr;
     return NS_OK;
 }
 
-nsISupports*
-nsXULTemplateBuilder::GetDatasource()
-{
-    return mCompDB ? mCompDB : mDataSource;
-}
-
 NS_IMETHODIMP
 nsXULTemplateBuilder::GetDatasource(nsISupports** aResult)
 {
-    NS_IF_ADDREF(*aResult = GetDatasource());
+    if (mCompDB)
+        NS_ADDREF(*aResult = mCompDB);
+    else
+        NS_IF_ADDREF(*aResult = mDataSource);
     return NS_OK;
 }
 
-void
-nsXULTemplateBuilder::SetDatasource(nsISupports* aDatasource,
-                                     ErrorResult& aError)
-{
-    mDataSource = aDatasource;
-    mCompDB = do_QueryInterface(mDataSource);
-
-    aError = Rebuild();
-}
-
 NS_IMETHODIMP
 nsXULTemplateBuilder::SetDatasource(nsISupports* aResult)
 {
-    ErrorResult rv;
-    SetDatasource(aResult, rv);
-    return rv.StealNSResult();
+    mDataSource = aResult;
+    mCompDB = do_QueryInterface(mDataSource);
+
+    return Rebuild();
 }
 
 NS_IMETHODIMP
 nsXULTemplateBuilder::GetDatabase(nsIRDFCompositeDataSource** aResult)
 {
-    NS_IF_ADDREF(*aResult = GetDatabase());
+    NS_IF_ADDREF(*aResult = mCompDB);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTemplateBuilder::GetQueryProcessor(nsIXULTemplateQueryProcessor** aResult)
 {
     NS_IF_ADDREF(*aResult = mQueryProcessor.get());
     return NS_OK;
 }
 
-void
-nsXULTemplateBuilder::AddRuleFilter(nsINode& aRule,
-                                    nsIXULTemplateRuleFilter* aFilter,
-                                    ErrorResult& aError)
+NS_IMETHODIMP
+nsXULTemplateBuilder::AddRuleFilter(nsIDOMNode* aRule, nsIXULTemplateRuleFilter* aFilter)
 {
+    if (!aRule || !aFilter)
+        return NS_ERROR_NULL_POINTER;
+
     // a custom rule filter may be added, one for each rule. If a new one is
     // added, it replaces the old one. Look for the right rule and set its
     // filter
 
-    nsIDOMNode* ruleAsDOMNode = aRule.AsDOMNode();
     int32_t count = mQuerySets.Length();
     for (int32_t q = 0; q < count; q++) {
         nsTemplateQuerySet* queryset = mQuerySets[q];
 
         int16_t rulecount = queryset->RuleCount();
         for (int16_t r = 0; r < rulecount; r++) {
             nsTemplateRule* rule = queryset->GetRuleAt(r);
 
             nsCOMPtr<nsIDOMNode> rulenode;
             rule->GetRuleNode(getter_AddRefs(rulenode));
-            if (ruleAsDOMNode == rulenode) {
+            if (aRule == rulenode) {
                 rule->SetRuleFilter(aFilter);
-                return;
+                return NS_OK;
             }
         }
     }
-}
-
-NS_IMETHODIMP
-nsXULTemplateBuilder::AddRuleFilter(nsIDOMNode* aRule, nsIXULTemplateRuleFilter* aFilter)
-{
-    nsCOMPtr<nsINode> rule = do_QueryInterface(aRule);
-    if (!rule) {
-        return NS_ERROR_NULL_POINTER;
-    }
-
-    NS_ENSURE_ARG_POINTER(aFilter);
-
-    ErrorResult rv;
-    AddRuleFilter(*rule, aFilter, rv);
-    return rv.StealNSResult();
-}
-
-void
-nsXULTemplateBuilder::Rebuild(ErrorResult& aError)
-{
-    int32_t i;
-
-    for (i = mListeners.Length() - 1; i >= 0; --i) {
-        mListeners[i]->WillRebuild(this);
-    }
-
-    aError = RebuildAll();
-
-    for (i = mListeners.Length() - 1; i >= 0; --i) {
-        mListeners[i]->DidRebuild(this);
-    }
+
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTemplateBuilder::Rebuild()
 {
-    ErrorResult rv;
-    Rebuild(rv);
-    return rv.StealNSResult();
+    int32_t i;
+
+    for (i = mListeners.Count() - 1; i >= 0; --i) {
+        mListeners[i]->WillRebuild(this);
+    }
+
+    nsresult rv = RebuildAll();
+
+    for (i = mListeners.Count() - 1; i >= 0; --i) {
+        mListeners[i]->DidRebuild(this);
+    }
+
+    return rv;
 }
 
-void
-nsXULTemplateBuilder::Refresh(ErrorResult& aError)
+NS_IMETHODIMP
+nsXULTemplateBuilder::Refresh()
 {
-    if (!mCompDB) {
-        aError.Throw(NS_ERROR_FAILURE);
-        return;
-    }
+    nsresult rv;
+
+    if (!mCompDB)
+        return NS_ERROR_FAILURE;
 
     nsCOMPtr<nsISimpleEnumerator> dslist;
-    aError = mCompDB->GetDataSources(getter_AddRefs(dslist));
-    if (aError.Failed()) {
-        return;
-    }
+    rv = mCompDB->GetDataSources(getter_AddRefs(dslist));
+    NS_ENSURE_SUCCESS(rv, rv);
 
     bool hasMore;
     nsCOMPtr<nsISupports> next;
     nsCOMPtr<nsIRDFRemoteDataSource> rds;
 
     while(NS_SUCCEEDED(dslist->HasMoreElements(&hasMore)) && hasMore) {
         dslist->GetNext(getter_AddRefs(next));
         if (next && (rds = do_QueryInterface(next))) {
             rds->Refresh(false);
         }
     }
 
     // XXXbsmedberg: it would be kinda nice to install an async nsIRDFXMLSink
     // observer and call rebuild() once the load is complete. See bug 254600.
+
+    return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXULTemplateBuilder::Refresh()
+nsXULTemplateBuilder::Init(nsIContent* aElement)
 {
-    ErrorResult rv;
-    Refresh(rv);
-    return rv.StealNSResult();
-}
-
-nsresult
-nsXULTemplateBuilder::Init()
-{
-    nsresult rv = InitGlobals();
-    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
+    mRoot = aElement;
 
     nsCOMPtr<nsIDocument> doc = mRoot->GetComposedDoc();
     NS_ASSERTION(doc, "element has no document");
     if (! doc)
         return NS_ERROR_UNEXPECTED;
 
     bool shouldDelay;
-    rv = LoadDataSources(doc, &shouldDelay);
+    nsresult rv = LoadDataSources(doc, &shouldDelay);
 
     if (NS_SUCCEEDED(rv)) {
         StartObserving(doc);
     }
 
     return rv;
 }
 
@@ -494,91 +443,60 @@ nsXULTemplateBuilder::CreateContents(nsI
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTemplateBuilder::HasGeneratedContent(nsIRDFResource* aResource,
                                           nsIAtom* aTag,
                                           bool* aGenerated)
 {
-    ErrorResult rv;
-    const nsAString& tag = aTag ? nsDependentAtomString(aTag) : NullString();
-    *aGenerated = HasGeneratedContent(aResource, tag, rv);
-    return rv.StealNSResult();
-}
-
-void
-nsXULTemplateBuilder::AddResult(nsIXULTemplateResult* aResult,
-                                nsINode& aQueryNode,
-                                ErrorResult& aError)
-{
-    aError = UpdateResult(nullptr, aResult, &aQueryNode);
+    *aGenerated = false;
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTemplateBuilder::AddResult(nsIXULTemplateResult* aResult,
                                 nsIDOMNode* aQueryNode)
 {
     NS_ENSURE_ARG_POINTER(aResult);
     NS_ENSURE_ARG_POINTER(aQueryNode);
 
-    ErrorResult rv;
-    nsCOMPtr<nsINode> queryNode = do_QueryInterface(aQueryNode);
-    AddResult(aResult, *queryNode, rv);
-    return rv.StealNSResult();
-}
-
-void
-nsXULTemplateBuilder::RemoveResult(nsIXULTemplateResult* aResult,
-                                   ErrorResult& aError)
-{
-    aError = UpdateResult(aResult, nullptr, nullptr);
+    return UpdateResult(nullptr, aResult, aQueryNode);
 }
 
 NS_IMETHODIMP
 nsXULTemplateBuilder::RemoveResult(nsIXULTemplateResult* aResult)
 {
     NS_ENSURE_ARG_POINTER(aResult);
 
-    ErrorResult rv;
-    RemoveResult(aResult, rv);
-    return rv.StealNSResult();
-}
-
-void
-nsXULTemplateBuilder::ReplaceResult(nsIXULTemplateResult* aOldResult,
-                                    nsIXULTemplateResult* aNewResult,
-                                    nsINode& aQueryNode,
-                                    ErrorResult& aError)
-{
-    aError = UpdateResult(aOldResult, nullptr, nullptr);
-    if (!aError.Failed()) {
-        aError = UpdateResult(nullptr, aNewResult, &aQueryNode);
-    }
+    return UpdateResult(aResult, nullptr, nullptr);
 }
 
 NS_IMETHODIMP
 nsXULTemplateBuilder::ReplaceResult(nsIXULTemplateResult* aOldResult,
                                     nsIXULTemplateResult* aNewResult,
                                     nsIDOMNode* aQueryNode)
 {
     NS_ENSURE_ARG_POINTER(aOldResult);
     NS_ENSURE_ARG_POINTER(aNewResult);
     NS_ENSURE_ARG_POINTER(aQueryNode);
 
-    nsCOMPtr<nsINode> queryNode = do_QueryInterface(aQueryNode);
-    ErrorResult rv;
-    ReplaceResult(aOldResult, aNewResult, *queryNode, rv);
-    return rv.StealNSResult();
+    // just remove the old result and then add a new result separately
+
+    nsresult rv = UpdateResult(aOldResult, nullptr, nullptr);
+    if (NS_FAILED(rv))
+        return rv;
+
+    return UpdateResult(nullptr, aNewResult, aQueryNode);
 }
 
 nsresult
 nsXULTemplateBuilder::UpdateResult(nsIXULTemplateResult* aOldResult,
                                    nsIXULTemplateResult* aNewResult,
-                                   nsINode* aQueryNode)
+                                   nsIDOMNode* aQueryNode)
 {
     MOZ_LOG(gXULTemplateLog, LogLevel::Info,
            ("nsXULTemplateBuilder::UpdateResult %p %p %p",
            aOldResult, aNewResult, aQueryNode));
 
     if (!mRoot || !mQueriesCompiled)
       return NS_OK;
 
@@ -1055,123 +973,91 @@ nsXULTemplateBuilder::UpdateResultInCont
         nsTemplateMatch::Destroy(removedmatch, true);
 
     if (mFlags & eLoggingEnabled && newmatch)
         OutputMatchToLog(aNewId, newmatch, true);
 
     return rv;
 }
 
-void
-nsXULTemplateBuilder::ResultBindingChanged(nsIXULTemplateResult* aResult,
-                                           ErrorResult& aError)
+NS_IMETHODIMP
+nsXULTemplateBuilder::ResultBindingChanged(nsIXULTemplateResult* aResult)
 {
     // A binding update is used when only the values of the bindings have
     // changed, so the same rule still applies. Just synchronize the content.
     // The new result will have the new values.
-    if (mRoot && mQueriesCompiled) {
-        aError = SynchronizeResult(aResult);
-    }
-}
-
-NS_IMETHODIMP
-nsXULTemplateBuilder::ResultBindingChanged(nsIXULTemplateResult* aResult)
-{
     NS_ENSURE_ARG_POINTER(aResult);
 
-    ErrorResult rv;
-    ResultBindingChanged(aResult, rv);
-    return rv.StealNSResult();
+    if (!mRoot || !mQueriesCompiled)
+      return NS_OK;
+
+    return SynchronizeResult(aResult);
 }
 
 NS_IMETHODIMP
 nsXULTemplateBuilder::GetRootResult(nsIXULTemplateResult** aResult)
 {
-  NS_IF_ADDREF(*aResult = GetRootResult());
+  *aResult = mRootResult;
+  NS_IF_ADDREF(*aResult);
   return NS_OK;
 }
 
-nsIXULTemplateResult*
-nsXULTemplateBuilder::GetResultForId(const nsAString& aId, ErrorResult& aError)
+NS_IMETHODIMP
+nsXULTemplateBuilder::GetResultForId(const nsAString& aId,
+                                     nsIXULTemplateResult** aResult)
 {
-    if (aId.IsEmpty()) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return nullptr;
-    }
+    if (aId.IsEmpty())
+        return NS_ERROR_INVALID_ARG;
 
     nsCOMPtr<nsIRDFResource> resource;
     gRDFService->GetUnicodeResource(aId, getter_AddRefs(resource));
 
+    *aResult = nullptr;
+
     nsTemplateMatch* match;
     if (mMatchMap.Get(resource, &match)) {
         // find the active match
         while (match) {
             if (match->IsActive()) {
-                return match->mResult;
+                *aResult = match->mResult;
+                NS_IF_ADDREF(*aResult);
+                break;
             }
             match = match->mNext;
         }
     }
 
-    return nullptr;
-}
-
-NS_IMETHODIMP
-nsXULTemplateBuilder::GetResultForId(const nsAString& aId,
-                                     nsIXULTemplateResult** aResult)
-{
-    ErrorResult rv;
-    NS_IF_ADDREF(*aResult = GetResultForId(aId, rv));
-    return rv.StealNSResult();
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTemplateBuilder::GetResultForContent(nsIDOMElement* aContent,
                                           nsIXULTemplateResult** aResult)
 {
-    nsCOMPtr<Element> element = do_QueryInterface(aContent);
-    NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
-    NS_IF_ADDREF(*aResult = GetResultForContent(*element));
+    *aResult = nullptr;
     return NS_OK;
 }
 
-void
-nsXULTemplateBuilder::AddListener(XULBuilderListener& aListener)
-{
-    CallbackObjectHolder<XULBuilderListener, nsIXULBuilderListener>
-        holder(&aListener);
-    mListeners.AppendElement(holder.ToXPCOMCallback());
-}
-
 NS_IMETHODIMP
 nsXULTemplateBuilder::AddListener(nsIXULBuilderListener* aListener)
 {
     NS_ENSURE_ARG(aListener);
 
-    if (!mListeners.AppendElement(aListener))
+    if (!mListeners.AppendObject(aListener))
         return NS_ERROR_OUT_OF_MEMORY;
 
     return NS_OK;
 }
 
-void
-nsXULTemplateBuilder::RemoveListener(XULBuilderListener& aListener)
-{
-    CallbackObjectHolder<XULBuilderListener, nsIXULBuilderListener>
-        holder(&aListener);
-    nsCOMPtr<nsIXULBuilderListener> listener(holder.ToXPCOMCallback());
-    mListeners.RemoveElement(listener);
-}
-
 NS_IMETHODIMP
 nsXULTemplateBuilder::RemoveListener(nsIXULBuilderListener* aListener)
 {
     NS_ENSURE_ARG(aListener);
 
-    mListeners.RemoveElement(aListener);
+    mListeners.RemoveObject(aListener);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTemplateBuilder::Observe(nsISupports* aSubject,
                               const char* aTopic,
                               const char16_t* aData)
--- a/dom/xul/templates/nsXULTemplateBuilder.h
+++ b/dom/xul/templates/nsXULTemplateBuilder.h
@@ -1,126 +1,68 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 nsXULTemplateBuilder_h__
 #define nsXULTemplateBuilder_h__
 
-#include "mozilla/dom/Element.h"
 #include "nsStubDocumentObserver.h"
+#include "nsIScriptSecurityManager.h"
 #include "nsIObserver.h"
+#include "nsIRDFCompositeDataSource.h"
+#include "nsIRDFContainer.h"
+#include "nsIRDFContainerUtils.h"
+#include "nsIRDFDataSource.h"
+#include "nsIRDFObserver.h"
+#include "nsIRDFService.h"
 #include "nsIXULTemplateBuilder.h"
+
 #include "nsCOMArray.h"
 #include "nsTArray.h"
 #include "nsDataHashtable.h"
+#include "nsTemplateRule.h"
+#include "nsTemplateMatch.h"
+#include "nsIXULTemplateQueryProcessor.h"
 #include "nsCycleCollectionParticipant.h"
 
 #include "mozilla/Logging.h"
 extern mozilla::LazyLogModule gXULTemplateLog;
 
+class nsIContent;
 class nsIObserverService;
 class nsIRDFCompositeDataSource;
-class nsIRDFContainerUtils;
-class nsIRDFDataSource;
-class nsIRDFService;
-class nsIScriptSecurityManager;
-class nsIXULTemplateQueryProcessor;
-class nsTemplateCondition;
-class nsTemplateRule;
-class nsTemplateMatch;
-class nsTemplateQuerySet;
-
-namespace mozilla {
-namespace dom {
-
-class XULBuilderListener;
-
-} // namespace dom
-} // namespace mozilla
-
 
 /**
  * An object that translates an RDF graph into a presentation using a
  * set of rules.
  */
 class nsXULTemplateBuilder : public nsIXULTemplateBuilder,
                              public nsIObserver,
-                             public nsStubDocumentObserver,
-                             public nsWrapperCache
+                             public nsStubDocumentObserver
 {
     void CleanUp(bool aIsFinal);
     void DestroyMatchMap();
 
 public:
-    nsresult Init();
+    nsXULTemplateBuilder();
 
     nsresult InitGlobals();
 
     /**
      * Clear the template builder structures. The aIsFinal flag is set to true
      * when the template is going away.
      */
     virtual void Uninit(bool aIsFinal);
 
     // nsISupports interface
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsXULTemplateBuilder,
-                                                           nsIXULTemplateBuilder)
-
-    virtual JSObject* WrapObject(JSContext* aCx,
-                                 JS::Handle<JSObject*> aGivenProto) override;
-    Element* GetParentObject()
-    {
-      return mRoot;
-    }
-
-    Element* GetRoot()
-    {
-        return mRoot;
-    }
-    nsISupports* GetDatasource();
-    void SetDatasource(nsISupports* aDatasource, mozilla::ErrorResult& aError);
-    nsIRDFCompositeDataSource* GetDatabase()
-    {
-        return mCompDB;
-    }
-    nsIXULTemplateResult* GetRootResult()
-    {
-        return mRootResult;
-    }
-    void Rebuild(mozilla::ErrorResult& aError);
-    void Refresh(mozilla::ErrorResult& aError);
-    void AddResult(nsIXULTemplateResult* aResult, nsINode& aQueryNode,
-                   mozilla::ErrorResult& aError);
-    void RemoveResult(nsIXULTemplateResult* aResult,
-                      mozilla::ErrorResult& aError);
-    void ReplaceResult(nsIXULTemplateResult* aOldResult,
-                       nsIXULTemplateResult* aNewResult,
-                       nsINode& aQueryNode,
-                       mozilla::ErrorResult& aError);
-    void ResultBindingChanged(nsIXULTemplateResult* aResult,
-                              mozilla::ErrorResult& aError);
-    nsIXULTemplateResult* GetResultForId(const nsAString& aId,
-                                         mozilla::ErrorResult& aError);
-    virtual nsIXULTemplateResult* GetResultForContent(Element& aElement)
-    {
-        return nullptr;
-    }
-    virtual bool HasGeneratedContent(nsIRDFResource* aResource,
-                                     const nsAString& aTag,
-                                     mozilla::ErrorResult& aError)
-    {
-        return false;
-    }
-    void AddRuleFilter(nsINode& aRule, nsIXULTemplateRuleFilter* aFilter,
-                       mozilla::ErrorResult& aError);
-    void AddListener(mozilla::dom::XULBuilderListener& aListener);
-    void RemoveListener(mozilla::dom::XULBuilderListener& aListener);
+    NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULTemplateBuilder,
+                                             nsIXULTemplateBuilder)
 
     // nsIXULTemplateBuilder interface
     NS_DECL_NSIXULTEMPLATEBUILDER
 
     // nsIObserver Interface
     NS_DECL_NSIOBSERVER
 
     // nsIMutationObserver
@@ -136,17 +78,17 @@ public:
      *
      * @param aOldResult result to remove
      * @param aNewResult result to add
      * @param aQueryNode query node for new result
      */
     nsresult
     UpdateResult(nsIXULTemplateResult* aOldResult,
                  nsIXULTemplateResult* aNewResult,
-                 nsINode* aQueryNode);
+                 nsIDOMNode* aQueryNode);
 
     /**
      * Remove an old result and/or add a new result from a specific container.
      *
      * @param aOldResult result to remove
      * @param aNewResult result to add
      * @param aQueryNode queryset for the new result
      * @param aOldId id of old result
@@ -384,34 +326,33 @@ public:
     /**
      * Convenience method which gets a resource for a result. If a result
      * doesn't have a resource set, it will create one from the result's id.
      */
     nsresult GetResultResource(nsIXULTemplateResult* aResult,
                                nsIRDFResource** aResource);
 
 protected:
-    explicit nsXULTemplateBuilder(Element* aElement);
     virtual ~nsXULTemplateBuilder();
 
     nsCOMPtr<nsISupports> mDataSource;
     nsCOMPtr<nsIRDFDataSource> mDB;
     nsCOMPtr<nsIRDFCompositeDataSource> mCompDB;
 
     /**
      * Circular reference, broken when the document is destroyed.
      */
-    nsCOMPtr<Element> mRoot;
+    nsCOMPtr<nsIContent> mRoot;
 
     /**
      * The root result, translated from the root element's ref
      */
     nsCOMPtr<nsIXULTemplateResult> mRootResult;
 
-    nsTArray<nsCOMPtr<nsIXULBuilderListener>> mListeners;
+    nsCOMArray<nsIXULBuilderListener> mListeners;
 
     /**
      * The query processor which generates results
      */
     nsCOMPtr<nsIXULTemplateQueryProcessor> mQueryProcessor;
 
     /**
      * The list of querysets
@@ -553,12 +494,9 @@ protected:
     void StopObserving();
 
     /**
      * Document that we're observing. Weak ref!
      */
     nsIDocument* mObservedDocument;
 };
 
-nsresult NS_NewXULContentBuilder(Element* aElement,
-                                 nsIXULTemplateBuilder** aBuilder);
-
 #endif // nsXULTemplateBuilder_h__
--- a/dom/xul/templates/nsXULTemplateQueryProcessorRDF.cpp
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorRDF.cpp
@@ -29,17 +29,16 @@
 #include "nsRDFTestNode.h"
 #include "nsXULContentUtils.h"
 #include "nsXULTemplateBuilder.h"
 #include "nsXULTemplateResultRDF.h"
 #include "nsXULTemplateResultSetRDF.h"
 #include "nsXULTemplateQueryProcessorRDF.h"
 #include "nsXULSortService.h"
 #include "nsIDocument.h"
-#include "nsIRDFCompositeDataSource.h"
 
 //----------------------------------------------------------------------
 
 #define PARSE_TYPE_INTEGER  "Integer"
 
 nsrefcnt                  nsXULTemplateQueryProcessorRDF::gRefCnt = 0;
 nsIRDFService*            nsXULTemplateQueryProcessorRDF::gRDFService;
 nsIRDFContainerUtils*     nsXULTemplateQueryProcessorRDF::gRDFContainerUtils;
--- a/dom/xul/templates/nsXULTemplateQueryProcessorStorage.cpp
+++ b/dom/xul/templates/nsXULTemplateQueryProcessorStorage.cpp
@@ -22,17 +22,16 @@
 #include "nsXULTemplateResultStorage.h"
 #include "nsXULContentUtils.h"
 #include "nsXULSortService.h"
 
 #include "mozIStorageService.h"
 #include "nsIChannel.h"
 #include "nsIDocument.h"
 #include "nsNetUtil.h"
-#include "nsTemplateMatch.h"
 
 //----------------------------------------------------------------------
 //
 // nsXULTemplateResultSetStorage
 //
 
 NS_IMPL_ISUPPORTS(nsXULTemplateResultSetStorage, nsISimpleEnumerator)
 
--- a/dom/xul/templates/nsXULTreeBuilder.cpp
+++ b/dom/xul/templates/nsXULTreeBuilder.cpp
@@ -14,66 +14,81 @@
 #include "nsITreeSelection.h"
 #include "nsITreeColumns.h"
 #include "nsTreeUtils.h"
 #include "nsIServiceManager.h"
 #include "nsReadableUtils.h"
 #include "nsQuickSort.h"
 #include "nsTemplateRule.h"
 #include "nsTemplateMatch.h"
-#include "nsTreeColumns.h"
 #include "nsGkAtoms.h"
 #include "nsXULContentUtils.h"
 #include "nsIXULSortService.h"
 #include "nsTArray.h"
 #include "nsUnicharUtils.h"
 #include "nsNameSpaceManager.h"
+#include "nsDOMClassInfoID.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsTreeContentView.h"
 #include "nsIXULStore.h"
 #include "mozilla/BinarySearch.h"
-#include "mozilla/dom/DataTransfer.h"
-#include "mozilla/dom/TreeBoxObject.h"
-#include "mozilla/dom/XULTemplateBuilderBinding.h"
 
 // For security check
 #include "nsIDocument.h"
 
+//----------------------------------------------------------------------
+
+nsresult
+NS_NewXULTreeBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult)
+{
+    *aResult = nullptr;
+
+    NS_PRECONDITION(aOuter == nullptr, "no aggregation");
+    if (aOuter)
+        return NS_ERROR_NO_AGGREGATION;
+
+    nsresult rv;
+    nsXULTreeBuilder* result = new nsXULTreeBuilder();
+    NS_ADDREF(result); // stabilize
+
+    rv = result->InitGlobals();
+
+    if (NS_SUCCEEDED(rv))
+        rv = result->QueryInterface(aIID, aResult);
+
+    NS_RELEASE(result);
+    return rv;
+}
+
 NS_IMPL_ADDREF_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder)
 NS_IMPL_RELEASE_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder)
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder,
                                    mBoxObject,
                                    mSelection,
                                    mPersistStateStore,
                                    mLocalStore,
                                    mObservers)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXULTreeBuilder)
     NS_INTERFACE_MAP_ENTRY(nsIXULTreeBuilder)
     NS_INTERFACE_MAP_ENTRY(nsITreeView)
+    NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULTreeBuilder)
 NS_INTERFACE_MAP_END_INHERITING(nsXULTemplateBuilder)
 
 
-nsXULTreeBuilder::nsXULTreeBuilder(Element* aElement)
-    : nsXULTemplateBuilder(aElement),
-      mSortDirection(eDirection_Natural), mSortHints(0)
+nsXULTreeBuilder::nsXULTreeBuilder()
+    : mSortDirection(eDirection_Natural), mSortHints(0)
 {
 }
 
 nsXULTreeBuilder::~nsXULTreeBuilder()
 {
 }
 
-JSObject* 
-nsXULTreeBuilder::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-    return XULTreeBuilderBinding::Wrap(aCx, this, aGivenProto);
-}
-
 void
 nsXULTreeBuilder::Uninit(bool aIsFinal)
 {
     int32_t count = mRows.Count();
     mRows.Clear();
 
     if (mBoxObject) {
         mBoxObject->BeginUpdateBatch();
@@ -87,122 +102,87 @@ nsXULTreeBuilder::Uninit(bool aIsFinal)
 }
 
 
 //----------------------------------------------------------------------
 //
 // nsIXULTreeBuilder methods
 //
 
-already_AddRefed<nsIRDFResource>
-nsXULTreeBuilder::GetResourceAtIndex(int32_t aRowIndex, ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRowIndex)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return nullptr;
-    }
-
-    nsCOMPtr<nsIRDFResource> result;
-    aError = GetResourceFor(aRowIndex, getter_AddRefs(result));
-    return result.forget();
-}
-
 NS_IMETHODIMP
 nsXULTreeBuilder::GetResourceAtIndex(int32_t aRowIndex, nsIRDFResource** aResult)
 {
-    ErrorResult rv;
-    *aResult = GetResourceAtIndex(aRowIndex, rv).take();
-    return rv.StealNSResult();
-}
+    if (aRowIndex < 0 || aRowIndex >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
-int32_t
-nsXULTreeBuilder::GetIndexOfResource(nsIRDFResource* aResource,
-                                     ErrorResult& aError)
-{
-    nsTreeRows::iterator iter = mRows.FindByResource(aResource);
-    return iter == mRows.Last() ? -1 : iter.GetRowIndex();
+    return GetResourceFor(aRowIndex, aResult);
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::GetIndexOfResource(nsIRDFResource* aResource, int32_t* aResult)
 {
     NS_ENSURE_ARG_POINTER(aResource);
-
-    ErrorResult rv;
-    *aResult = GetIndexOfResource(aResource, rv);
-    return rv.StealNSResult();
-}
-
-void
-nsXULTreeBuilder::AddObserver(XULTreeBuilderObserver& aObserver)
-{
-    CallbackObjectHolder<XULTreeBuilderObserver, nsIXULTreeBuilderObserver>
-        holder(&aObserver);
-    mObservers.AppendElement(holder.ToXPCOMCallback());
+    nsTreeRows::iterator iter = mRows.FindByResource(aResource);
+    if (iter == mRows.Last())
+        *aResult = -1;
+    else
+        *aResult = iter.GetRowIndex();
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::AddObserver(nsIXULTreeBuilderObserver* aObserver)
 {
-    mObservers.AppendElement(aObserver);
-    return NS_OK;
-}
-
-void
-nsXULTreeBuilder::RemoveObserver(XULTreeBuilderObserver& aObserver)
-{
-    CallbackObjectHolder<XULTreeBuilderObserver, nsIXULTreeBuilderObserver>
-        holder(&aObserver);
-    nsCOMPtr<nsIXULTreeBuilderObserver> observer(holder.ToXPCOMCallback());
-    mObservers.RemoveElement(observer);
+    return mObservers.AppendObject(aObserver) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::RemoveObserver(nsIXULTreeBuilderObserver* aObserver)
 {
-    mObservers.RemoveElement(aObserver);
-    return NS_OK;
+    return mObservers.RemoveObject(aObserver) ? NS_OK : NS_ERROR_FAILURE;
 }
 
-void
-nsXULTreeBuilder::Sort(Element& aElement)
+NS_IMETHODIMP
+nsXULTreeBuilder::Sort(nsIDOMElement* aElement)
 {
-    if (aElement.AttrValueIs(kNameSpaceID_None, nsGkAtoms::sortLocked,
-                             nsGkAtoms::_true, eCaseMatters)) {
-        return;
-    }
+    nsCOMPtr<nsIContent> header = do_QueryInterface(aElement);
+    if (! header)
+        return NS_ERROR_FAILURE;
+
+    if (header->AttrValueIs(kNameSpaceID_None, nsGkAtoms::sortLocked,
+                            nsGkAtoms::_true, eCaseMatters))
+        return NS_OK;
 
     nsAutoString sort;
-    aElement.GetAttr(kNameSpaceID_None, nsGkAtoms::sort, sort);
+    header->GetAttr(kNameSpaceID_None, nsGkAtoms::sort, sort);
 
-    if (sort.IsEmpty()) {
-        return;
-    }
+    if (sort.IsEmpty())
+        return NS_OK;
 
     // Grab the new sort variable
     mSortVariable = NS_Atomize(sort);
 
     nsAutoString hints;
-    aElement.GetAttr(kNameSpaceID_None, nsGkAtoms::sorthints, hints);
+    header->GetAttr(kNameSpaceID_None, nsGkAtoms::sorthints, hints);
 
     bool hasNaturalState = true;
     nsWhitespaceTokenizer tokenizer(hints);
     while (tokenizer.hasMoreTokens()) {
       const nsDependentSubstring& token(tokenizer.nextToken());
       if (token.EqualsLiteral("comparecase"))
         mSortHints |= nsIXULSortService::SORT_COMPARECASE;
       else if (token.EqualsLiteral("integer"))
         mSortHints |= nsIXULSortService::SORT_INTEGER;
       else if (token.EqualsLiteral("twostate"))
         hasNaturalState = false;
     }
 
     // Cycle the sort direction
     nsAutoString dir;
-    aElement.GetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection, dir);
+    header->GetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection, dir);
 
     if (dir.EqualsLiteral("ascending")) {
         dir.AssignLiteral("descending");
         mSortDirection = eDirection_Descending;
     }
     else if (hasNaturalState && dir.EqualsLiteral("descending")) {
         dir.AssignLiteral("natural");
         mSortDirection = eDirection_Natural;
@@ -213,480 +193,346 @@ nsXULTreeBuilder::Sort(Element& aElement
     }
 
     // Sort it.
     SortSubtree(mRows.GetRoot());
     mRows.InvalidateCachedRow();
     if (mBoxObject) 
         mBoxObject->Invalidate();
 
-    nsTreeUtils::UpdateSortIndicators(&aElement, dir);
-}
+    nsTreeUtils::UpdateSortIndicators(header, dir);
 
-NS_IMETHODIMP
-nsXULTreeBuilder::Sort(nsIDOMElement* aElement)
-{
-    nsCOMPtr<Element> header = do_QueryInterface(aElement);
-    if (!header) {
-        return NS_ERROR_FAILURE;
-    }
-    Sort(*header);
     return NS_OK;
 }
 
 //----------------------------------------------------------------------
 //
 // nsITreeView methods
 //
 
 NS_IMETHODIMP
 nsXULTreeBuilder::GetRowCount(int32_t* aRowCount)
 {
-    *aRowCount = RowCount();
+    *aRowCount = mRows.Count();
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::GetSelection(nsITreeSelection** aSelection)
 {
-    NS_IF_ADDREF(*aSelection = GetSelection());
+    NS_IF_ADDREF(*aSelection = mSelection.get());
     return NS_OK;
 }
 
-void
-nsXULTreeBuilder::SetSelection(nsITreeSelection* aSelection,
-                               ErrorResult& aError)
-{
-    if (aSelection && !nsTreeContentView::CanTrustTreeSelection(aSelection)) {
-        aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
-        return;
-    }
-
-    mSelection = aSelection;
-}
-
 NS_IMETHODIMP
 nsXULTreeBuilder::SetSelection(nsITreeSelection* aSelection)
 {
-    ErrorResult rv;
-    SetSelection(aSelection, rv);
-    return rv.StealNSResult();
+    NS_ENSURE_TRUE(!aSelection ||
+                   nsTreeContentView::CanTrustTreeSelection(aSelection),
+                   NS_ERROR_DOM_SECURITY_ERR);
+    mSelection = aSelection;
+    return NS_OK;
 }
 
-void
-nsXULTreeBuilder::GetRowProperties(int32_t aRow, nsAString& aProperties,
-                                   ErrorResult& aError)
+NS_IMETHODIMP
+nsXULTreeBuilder::GetRowProperties(int32_t aIndex, nsAString& aProps)
 {
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return;
-    }
+    NS_PRECONDITION(aIndex >= 0 && aIndex < mRows.Count(), "bad row");
+    if (aIndex < 0 || aIndex >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
     nsCOMPtr<nsIContent> row;
-    GetTemplateActionRowFor(aRow, getter_AddRefs(row));
+    GetTemplateActionRowFor(aIndex, getter_AddRefs(row));
     if (row) {
         nsAutoString raw;
         row->GetAttr(kNameSpaceID_None, nsGkAtoms::properties, raw);
 
         if (!raw.IsEmpty()) {
-            SubstituteText(mRows[aRow]->mMatch->mResult, raw, aProperties);
+            SubstituteText(mRows[aIndex]->mMatch->mResult, raw, aProps);
         }
     }
-}
 
-NS_IMETHODIMP
-nsXULTreeBuilder::GetRowProperties(int32_t aIndex, nsAString& aProps)
-{
-    ErrorResult rv;
-    GetRowProperties(aIndex, aProps, rv);
-    return rv.StealNSResult();
-}
-
-void
-nsXULTreeBuilder::GetCellProperties(int32_t aRow, nsTreeColumn& aColumn,
-                                    nsAString& aProperties, ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return;
-    }
-
-    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
-    if (cell) {
-        nsAutoString raw;
-        cell->GetAttr(kNameSpaceID_None, nsGkAtoms::properties, raw);
-
-        if (!raw.IsEmpty()) {
-            SubstituteText(mRows[aRow]->mMatch->mResult, raw, aProperties);
-        }
-    }
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::GetCellProperties(int32_t aRow, nsITreeColumn* aCol,
                                     nsAString& aProps)
 {
-    RefPtr<nsTreeColumn> col = nsTreeColumn::From(aCol);
-    NS_ENSURE_ARG(col);
+    NS_ENSURE_ARG_POINTER(aCol);
+    NS_PRECONDITION(aRow >= 0 && aRow < mRows.Count(), "bad row");
+    if (aRow < 0 || aRow >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
-    ErrorResult rv;
-    GetCellProperties(aRow, *col, aProps, rv);
-    return rv.StealNSResult();
+    nsCOMPtr<nsIContent> cell;
+    GetTemplateActionCellFor(aRow, aCol, getter_AddRefs(cell));
+    if (cell) {
+        nsAutoString raw;
+        cell->GetAttr(kNameSpaceID_None, nsGkAtoms::properties, raw);
+
+        if (!raw.IsEmpty()) {
+            SubstituteText(mRows[aRow]->mMatch->mResult, raw, aProps);
+        }
+    }
+
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::GetColumnProperties(nsITreeColumn* aCol, nsAString& aProps)
 {
     NS_ENSURE_ARG_POINTER(aCol);
     // XXX sortactive fu
     return NS_OK;
 }
 
-bool
-nsXULTreeBuilder::IsContainer(int32_t aRow, ErrorResult& aError)
+NS_IMETHODIMP
+nsXULTreeBuilder::IsContainer(int32_t aIndex, bool* aResult)
 {
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return false;
-    }
+    NS_PRECONDITION(aIndex >= 0 && aIndex < mRows.Count(), "bad row");
+    if (aIndex < 0 || aIndex >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
-    nsTreeRows::iterator iter = mRows[aRow];
+    nsTreeRows::iterator iter = mRows[aIndex];
 
     bool isContainer;
     iter->mMatch->mResult->GetIsContainer(&isContainer);
 
     iter->mContainerType = isContainer
         ? nsTreeRows::eContainerType_Container
         : nsTreeRows::eContainerType_Noncontainer;
 
-    return iter->mContainerType == nsTreeRows::eContainerType_Container;
+    *aResult = (iter->mContainerType == nsTreeRows::eContainerType_Container);
+    return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXULTreeBuilder::IsContainer(int32_t aIndex, bool* aResult)
+nsXULTreeBuilder::IsContainerOpen(int32_t aIndex, bool* aOpen)
 {
-    ErrorResult rv;
-    *aResult = IsContainer(aIndex, rv);
-    return rv.StealNSResult();
-}
+    NS_PRECONDITION(aIndex >= 0 && aIndex < mRows.Count(), "bad row");
+    if (aIndex < 0 || aIndex >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
-bool
-nsXULTreeBuilder::IsContainerOpen(int32_t aRow, ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return false;
-    }
-
-    nsTreeRows::iterator iter = mRows[aRow];
+    nsTreeRows::iterator iter = mRows[aIndex];
 
     if (iter->mContainerState == nsTreeRows::eContainerState_Unknown) {
         bool isOpen = IsContainerOpen(iter->mMatch->mResult);
 
         iter->mContainerState = isOpen
             ? nsTreeRows::eContainerState_Open
             : nsTreeRows::eContainerState_Closed;
     }
 
-    return iter->mContainerState == nsTreeRows::eContainerState_Open;
+    *aOpen = (iter->mContainerState == nsTreeRows::eContainerState_Open);
+    return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXULTreeBuilder::IsContainerOpen(int32_t aIndex, bool* aOpen)
+nsXULTreeBuilder::IsContainerEmpty(int32_t aIndex, bool* aResult)
 {
-    ErrorResult rv;
-    *aOpen = IsContainerOpen(aIndex, rv);
-    return rv.StealNSResult();
-}
+    NS_PRECONDITION(aIndex >= 0 && aIndex < mRows.Count(), "bad row");
+    if (aIndex < 0 || aIndex >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
-bool
-nsXULTreeBuilder::IsContainerEmpty(int32_t aRow, ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return false;
-    }
-
-    nsTreeRows::iterator iter = mRows[aRow];
+    nsTreeRows::iterator iter = mRows[aIndex];
     NS_ASSERTION(iter->mContainerType == nsTreeRows::eContainerType_Container,
                  "asking for empty state on non-container");
 
     // if recursion is disabled, pretend that the container is empty. This
     // ensures that folders are still displayed as such, yet won't display
     // their children
     if ((mFlags & eDontRecurse) && (iter->mMatch->mResult != mRootResult)) {
-        return true;
+        *aResult = true;
+        return NS_OK;
     }
 
     if (iter->mContainerFill == nsTreeRows::eContainerFill_Unknown) {
         bool isEmpty;
         iter->mMatch->mResult->GetIsEmpty(&isEmpty);
 
         iter->mContainerFill = isEmpty
             ? nsTreeRows::eContainerFill_Empty
             : nsTreeRows::eContainerFill_Nonempty;
     }
 
-    return iter->mContainerFill == nsTreeRows::eContainerFill_Empty;
-}
-
-NS_IMETHODIMP
-nsXULTreeBuilder::IsContainerEmpty(int32_t aIndex, bool* aResult)
-{
-    ErrorResult rv;
-    *aResult = IsContainerEmpty(aIndex, rv);
-    return rv.StealNSResult();
-}
-
-bool
-nsXULTreeBuilder::IsSeparator(int32_t aRow, ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return false;
-    }
-
-    nsAutoString type;
-    nsTreeRows::Row& row = *(mRows[aRow]);
-    row.mMatch->mResult->GetType(type);
-
-    return type.EqualsLiteral("separator");
+    *aResult = (iter->mContainerFill == nsTreeRows::eContainerFill_Empty);
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::IsSeparator(int32_t aIndex, bool* aResult)
 {
-    ErrorResult rv;
-    *aResult = IsSeparator(aIndex, rv);
-    return rv.StealNSResult();
+    NS_PRECONDITION(aIndex >= 0 && aIndex < mRows.Count(), "bad row");
+    if (aIndex < 0 || aIndex >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
+
+    nsAutoString type;
+    nsTreeRows::Row& row = *(mRows[aIndex]);
+    row.mMatch->mResult->GetType(type);
+
+    *aResult = type.EqualsLiteral("separator");
+
+    return NS_OK;
 }
 
-int32_t
-nsXULTreeBuilder::GetParentIndex(int32_t aRow, ErrorResult& aError)
+NS_IMETHODIMP
+nsXULTreeBuilder::GetParentIndex(int32_t aRowIndex, int32_t* aResult)
 {
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return -1;
-    }
+    NS_PRECONDITION(aRowIndex >= 0 && aRowIndex < mRows.Count(), "bad row");
+    if (aRowIndex < 0 || aRowIndex >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
     // Construct a path to the row
-    nsTreeRows::iterator iter = mRows[aRow];
+    nsTreeRows::iterator iter = mRows[aRowIndex];
 
     // The parent of the row will be at the top of the path
     nsTreeRows::Subtree* parent = iter.GetParent();
 
     // Now walk through our previous siblings, subtracting off each
     // one's subtree size
     int32_t index = iter.GetChildIndex();
     while (--index >= 0)
-        aRow -= mRows.GetSubtreeSizeFor(parent, index) + 1;
+        aRowIndex -= mRows.GetSubtreeSizeFor(parent, index) + 1;
 
     // Now the parent's index will be the first row's index, less one.
-    return aRow - 1;
+    *aResult = aRowIndex - 1;
+    return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXULTreeBuilder::GetParentIndex(int32_t aRowIndex, int32_t* aResult)
+nsXULTreeBuilder::HasNextSibling(int32_t aRowIndex, int32_t aAfterIndex, bool* aResult)
 {
-    ErrorResult rv;
-    *aResult = GetParentIndex(aRowIndex, rv);
-    return rv.StealNSResult();
-}
-
-bool
-nsXULTreeBuilder::HasNextSibling(int32_t aRow, int32_t aAfterIndex,
-                                 ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return false;
-    }
+    NS_PRECONDITION(aRowIndex >= 0 && aRowIndex < mRows.Count(), "bad row");
+    if (aRowIndex < 0 || aRowIndex >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
     // Construct a path to the row
-    nsTreeRows::iterator iter = mRows[aRow];
+    nsTreeRows::iterator iter = mRows[aRowIndex];
 
     // The parent of the row will be at the top of the path
     nsTreeRows::Subtree* parent = iter.GetParent();
 
     // We have a next sibling if the child is not the last in the
     // subtree.
-    return iter.GetChildIndex() != parent->Count() - 1;
-}
-
-NS_IMETHODIMP
-nsXULTreeBuilder::HasNextSibling(int32_t aRowIndex, int32_t aAfterIndex, bool* aResult)
-{
-    ErrorResult rv;
-    *aResult = HasNextSibling(aRowIndex, aAfterIndex, rv);
-    return rv.StealNSResult();
-}
-
-int32_t
-nsXULTreeBuilder::GetLevel(int32_t aRow, ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return -1;
-    }
-
-    // Construct a path to the row; the ``level'' is the path length
-    // less one.
-    nsTreeRows::iterator iter = mRows[aRow];
-    return iter.GetDepth() - 1;
+    *aResult = iter.GetChildIndex() != parent->Count() - 1;
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::GetLevel(int32_t aRowIndex, int32_t* aResult)
 {
-    ErrorResult rv;
-    *aResult = GetLevel(aRowIndex, rv);
-    return rv.StealNSResult();
-}
+    NS_PRECONDITION(aRowIndex >= 0 && aRowIndex < mRows.Count(), "bad row");
+    if (aRowIndex < 0 || aRowIndex >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
-void
-nsXULTreeBuilder::GetImageSrc(int32_t aRow, nsTreeColumn& aColumn,
-                              nsAString& aSrc, ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return;
-    }
-
-    // Find the <cell> that corresponds to the column we want.
-    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
-    if (cell) {
-        nsAutoString raw;
-        cell->GetAttr(kNameSpaceID_None, nsGkAtoms::src, raw);
-
-        SubstituteText(mRows[aRow]->mMatch->mResult, raw, aSrc);
-    } else {
-        aSrc.Truncate();
-    }
+    // Construct a path to the row; the ``level'' is the path length
+    // less one.
+    nsTreeRows::iterator iter = mRows[aRowIndex];
+    *aResult = iter.GetDepth() - 1;
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::GetImageSrc(int32_t aRow, nsITreeColumn* aCol, nsAString& aResult)
 {
-    RefPtr<nsTreeColumn> col = nsTreeColumn::From(aCol);
-    NS_ENSURE_ARG(col);
+    NS_ENSURE_ARG_POINTER(aCol);
+    NS_PRECONDITION(aRow >= 0 && aRow < mRows.Count(), "bad index");
+    if (aRow < 0 || aRow >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
-    ErrorResult rv;
-    GetImageSrc(aRow, *col, aResult, rv);
-    return rv.StealNSResult();
+    // Find the <cell> that corresponds to the column we want.
+    nsCOMPtr<nsIContent> cell;
+    GetTemplateActionCellFor(aRow, aCol, getter_AddRefs(cell));
+    if (cell) {
+        nsAutoString raw;
+        cell->GetAttr(kNameSpaceID_None, nsGkAtoms::src, raw);
+
+        SubstituteText(mRows[aRow]->mMatch->mResult, raw, aResult);
+    }
+    else
+        aResult.Truncate();
+
+    return NS_OK;
 }
 
-int32_t
-nsXULTreeBuilder::GetProgressMode(int32_t aRow, nsTreeColumn& aColumn,
-                                  ErrorResult& aError)
+
+NS_IMETHODIMP
+nsXULTreeBuilder::GetProgressMode(int32_t aRow, nsITreeColumn* aCol, int32_t* aResult)
 {
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return -1;
-    }
+    NS_ENSURE_ARG_POINTER(aCol);
+    NS_PRECONDITION(aRow >= 0 && aRow < mRows.Count(), "bad index");
+    if (aRow < 0 || aRow >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
+
+    *aResult = nsITreeView::PROGRESS_NONE;
 
     // Find the <cell> that corresponds to the column we want.
-    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
+    nsCOMPtr<nsIContent> cell;
+    GetTemplateActionCellFor(aRow, aCol, getter_AddRefs(cell));
     if (cell) {
         nsAutoString raw;
         cell->GetAttr(kNameSpaceID_None, nsGkAtoms::mode, raw);
 
         nsAutoString mode;
         SubstituteText(mRows[aRow]->mMatch->mResult, raw, mode);
 
-        if (mode.EqualsLiteral("normal")) {
-            return nsITreeView::PROGRESS_NORMAL;
-        }
-
-        if (mode.EqualsLiteral("undetermined")) {
-            return nsITreeView::PROGRESS_UNDETERMINED;
-        }
+        if (mode.EqualsLiteral("normal"))
+            *aResult = nsITreeView::PROGRESS_NORMAL;
+        else if (mode.EqualsLiteral("undetermined"))
+            *aResult = nsITreeView::PROGRESS_UNDETERMINED;
     }
 
-    return nsITreeView::PROGRESS_NONE;
-}
-
-NS_IMETHODIMP
-nsXULTreeBuilder::GetProgressMode(int32_t aRow, nsITreeColumn* aCol, int32_t* aResult)
-{
-    RefPtr<nsTreeColumn> col = nsTreeColumn::From(aCol);
-    NS_ENSURE_ARG(col);
-
-    ErrorResult rv;
-    *aResult = GetProgressMode(aRow, *col, rv);
-    return rv.StealNSResult();
-}
-
-void
-nsXULTreeBuilder::GetCellValue(int32_t aRow, nsTreeColumn& aColumn,
-                               nsAString& aValue, ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return;
-    }
-
-    // Find the <cell> that corresponds to the column we want.
-    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
-    if (cell) {
-        nsAutoString raw;
-        cell->GetAttr(kNameSpaceID_None, nsGkAtoms::value, raw);
-
-        SubstituteText(mRows[aRow]->mMatch->mResult, raw, aValue);
-    } else {
-        aValue.Truncate();
-    }
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::GetCellValue(int32_t aRow, nsITreeColumn* aCol, nsAString& aResult)
 {
-    RefPtr<nsTreeColumn> col = nsTreeColumn::From(aCol);
-    NS_ENSURE_ARG(col);
-
-    ErrorResult rv;
-    GetCellValue(aRow, *col, aResult, rv);
-    return rv.StealNSResult();
-}
-
-void
-nsXULTreeBuilder::GetCellText(int32_t aRow, nsTreeColumn& aColumn,
-                              nsAString& aText, ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return;
-    }
+    NS_ENSURE_ARG_POINTER(aCol);
+    NS_PRECONDITION(aRow >= 0 && aRow < mRows.Count(), "bad index");
+    if (aRow < 0 || aRow >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
     // Find the <cell> that corresponds to the column we want.
-    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
+    nsCOMPtr<nsIContent> cell;
+    GetTemplateActionCellFor(aRow, aCol, getter_AddRefs(cell));
     if (cell) {
         nsAutoString raw;
-        cell->GetAttr(kNameSpaceID_None, nsGkAtoms::label, raw);
+        cell->GetAttr(kNameSpaceID_None, nsGkAtoms::value, raw);
 
-        SubstituteText(mRows[aRow]->mMatch->mResult, raw, aText);
-    } else {
-        aText.Truncate();
+        SubstituteText(mRows[aRow]->mMatch->mResult, raw, aResult);
     }
+    else
+        aResult.Truncate();
+
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::GetCellText(int32_t aRow, nsITreeColumn* aCol, nsAString& aResult)
 {
-    RefPtr<nsTreeColumn> col = nsTreeColumn::From(aCol);
-    NS_ENSURE_ARG(col);
+    NS_ENSURE_ARG_POINTER(aCol);
+    NS_PRECONDITION(aRow >= 0 && aRow < mRows.Count(), "bad index");
+    if (aRow < 0 || aRow >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
-    ErrorResult rv;
-    GetCellText(aRow, *col, aResult, rv);
-    return rv.StealNSResult();
-}
+    // Find the <cell> that corresponds to the column we want.
+    nsCOMPtr<nsIContent> cell;
+    GetTemplateActionCellFor(aRow, aCol, getter_AddRefs(cell));
+    if (cell) {
+        nsAutoString raw;
+        cell->GetAttr(kNameSpaceID_None, nsGkAtoms::label, raw);
 
-void
-nsXULTreeBuilder::SetTree(TreeBoxObject* aTree, ErrorResult& aError)
-{
-    aError = SetTree(aTree);
+        SubstituteText(mRows[aRow]->mMatch->mResult, raw, aResult);
+
+    }
+    else
+        aResult.Truncate();
+
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::SetTree(nsITreeBoxObject* aTree)
 {
     mBoxObject = aTree;
 
     // If this is teardown time, then we're done.
@@ -710,345 +556,273 @@ nsXULTreeBuilder::SetTree(nsITreeBoxObje
 
     EnsureSortVariables();
     if (mSortVariable)
         SortSubtree(mRows.GetRoot());
 
     return NS_OK;
 }
 
-void
-nsXULTreeBuilder::ToggleOpenState(int32_t aRow, ErrorResult& aError)
+NS_IMETHODIMP
+nsXULTreeBuilder::ToggleOpenState(int32_t aIndex)
 {
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return;
-    }
+    if (aIndex < 0 || aIndex >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
-    nsIXULTemplateResult* result = mRows[aRow]->mMatch->mResult;
-    if (!result) {
-        aError.Throw(NS_ERROR_FAILURE);
-        return;
-    }
+    nsIXULTemplateResult* result = mRows[aIndex]->mMatch->mResult;
+    if (! result)
+        return NS_ERROR_FAILURE;
 
-    if (mFlags & eDontRecurse) {
-        return;
-    }
+    if (mFlags & eDontRecurse)
+        return NS_OK;
 
     if (result && result != mRootResult) {
         // don't open containers if child processing isn't allowed
         bool mayProcessChildren;
-        aError = result->GetMayProcessChildren(&mayProcessChildren);
-        if (aError.Failed() || !mayProcessChildren) {
-            return;
-        }
+        nsresult rv = result->GetMayProcessChildren(&mayProcessChildren);
+        if (NS_FAILED(rv) || !mayProcessChildren)
+            return rv;
     }
 
-    uint32_t count = mObservers.Length();
+    uint32_t count = mObservers.Count();
     for (uint32_t i = 0; i < count; ++i) {
-        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeElementAt(i);
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
         if (observer)
-            observer->OnToggleOpenState(aRow);
+            observer->OnToggleOpenState(aIndex);
     }
 
     if (mLocalStore && mRoot) {
         bool isOpen;
-        IsContainerOpen(aRow, &isOpen);
+        IsContainerOpen(aIndex, &isOpen);
 
         nsIDocument* doc = mRoot->GetComposedDoc();
         if (!doc) {
-            aError.Throw(NS_ERROR_FAILURE);
-            return;
+            return NS_ERROR_FAILURE;
         }
 
         nsIURI* docURI = doc->GetDocumentURI();
-        nsTreeRows::Row& row = *(mRows[aRow]);
+        nsTreeRows::Row& row = *(mRows[aIndex]);
         nsAutoString nodeid;
-        aError = row.mMatch->mResult->GetId(nodeid);
-        if (aError.Failed()) {
-            return;
+        nsresult rv = row.mMatch->mResult->GetId(nodeid);
+        if (NS_FAILED(rv)) {
+            return rv;
         }
 
         nsAutoCString utf8uri;
-        aError = docURI->GetSpec(utf8uri);
-        if (NS_WARN_IF(aError.Failed())) {
-            return;
+        rv = docURI->GetSpec(utf8uri);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+            return rv;
         }
         NS_ConvertUTF8toUTF16 uri(utf8uri);
 
         if (isOpen) {
             mLocalStore->RemoveValue(uri, nodeid, NS_LITERAL_STRING("open"));
-            CloseContainer(aRow);
+            CloseContainer(aIndex);
         } else {
             mLocalStore->SetValue(uri, nodeid, NS_LITERAL_STRING("open"),
                 NS_LITERAL_STRING("true"));
 
-            OpenContainer(aRow, result);
+            OpenContainer(aIndex, result);
         }
     }
-}
 
-NS_IMETHODIMP
-nsXULTreeBuilder::ToggleOpenState(int32_t aIndex)
-{
-    ErrorResult rv;
-    ToggleOpenState(aIndex, rv);
-    return rv.StealNSResult();
-}
-
-void
-nsXULTreeBuilder::CycleHeader(nsTreeColumn& aColumn, ErrorResult& aError)
-{
-    nsCOMPtr<nsIDOMElement> element;
-    aColumn.GetElement(getter_AddRefs(element));
-
-    nsAutoString id;
-    aColumn.GetId(id);
-
-    uint32_t count = mObservers.Length();
-    for (uint32_t i = 0; i < count; ++i) {
-        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeElementAt(i);
-        if (observer)
-            observer->OnCycleHeader(id.get(), element);
-    }
-
-    aError = Sort(element);
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::CycleHeader(nsITreeColumn* aCol)
 {
-    RefPtr<nsTreeColumn> col = nsTreeColumn::From(aCol);
-    NS_ENSURE_ARG(col);
+    NS_ENSURE_ARG_POINTER(aCol);
+    nsCOMPtr<nsIDOMElement> element;
+    aCol->GetElement(getter_AddRefs(element));
+
+    nsAutoString id;
+    aCol->GetId(id);
 
-    ErrorResult rv;
-    CycleHeader(*col, rv);
-    return rv.StealNSResult();
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnCycleHeader(id.get(), element);
+    }
+
+    return Sort(element);
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::SelectionChanged()
 {
-    uint32_t count = mObservers.Length();
+    uint32_t count = mObservers.Count();
     for (uint32_t i = 0; i < count; ++i) {
-        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeElementAt(i);
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
         if (observer)
             observer->OnSelectionChanged();
     }
 
     return NS_OK;
 }
 
-void
-nsXULTreeBuilder::CycleCell(int32_t aRow, nsTreeColumn& aColumn)
-{
-    nsAutoString id;
-    aColumn.GetId(id);
-
-    uint32_t count = mObservers.Length();
-    for (uint32_t i = 0; i < count; ++i) {
-        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeElementAt(i);
-        if (observer)
-            observer->OnCycleCell(aRow, id.get());
-    }
-}
-
 NS_IMETHODIMP
 nsXULTreeBuilder::CycleCell(int32_t aRow, nsITreeColumn* aCol)
 {
-    RefPtr<nsTreeColumn> col = nsTreeColumn::From(aCol);
-    NS_ENSURE_ARG(col);
+    NS_ENSURE_ARG_POINTER(aCol);
 
-    CycleCell(aRow, *col);
-    return NS_OK;
-}
+    nsAutoString id;
+    aCol->GetId(id);
 
-bool
-nsXULTreeBuilder::IsEditable(int32_t aRow, nsTreeColumn& aColumn,
-                             ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return false;
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnCycleCell(aRow, id.get());
     }
 
-    // Find the <cell> that corresponds to the column we want.
-    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
-    if (!cell) {
-        return true;
-    }
-
-    nsAutoString raw;
-    cell->GetAttr(kNameSpaceID_None, nsGkAtoms::editable, raw);
-
-    nsAutoString editable;
-    SubstituteText(mRows[aRow]->mMatch->mResult, raw, editable);
-
-    return !editable.EqualsLiteral("false");
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::IsEditable(int32_t aRow, nsITreeColumn* aCol, bool* _retval)
 {
-    RefPtr<nsTreeColumn> col = nsTreeColumn::From(aCol);
-    NS_ENSURE_ARG(col);
-
-    ErrorResult rv;
-    *_retval = IsEditable(aRow, *col, rv);
-    return rv.StealNSResult();
-}
+    *_retval = true;
+    NS_ENSURE_ARG_POINTER(aCol);
+    NS_PRECONDITION(aRow >= 0 && aRow < mRows.Count(), "bad index");
+    if (aRow < 0 || aRow >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
 
-bool
-nsXULTreeBuilder::IsSelectable(int32_t aRow, nsTreeColumn& aColumn,
-                               ErrorResult& aError)
-{
-    if (!IsValidRowIndex(aRow)) {
-        aError.Throw(NS_ERROR_INVALID_ARG);
-        return false;
+    // Find the <cell> that corresponds to the column we want.
+    nsCOMPtr<nsIContent> cell;
+    GetTemplateActionCellFor(aRow, aCol, getter_AddRefs(cell));
+    if (cell) {
+        nsAutoString raw;
+        cell->GetAttr(kNameSpaceID_None, nsGkAtoms::editable, raw);
+
+        nsAutoString editable;
+        SubstituteText(mRows[aRow]->mMatch->mResult, raw, editable);
+
+        if (editable.EqualsLiteral("false"))
+            *_retval = false;
     }
 
-    // Find the <cell> that corresponds to the column we want.
-    nsIContent* cell = GetTemplateActionCellFor(aRow, aColumn);
-    if (!cell) {
-        return true;
-    }
-
-    nsAutoString raw;
-    cell->GetAttr(kNameSpaceID_None, nsGkAtoms::selectable, raw);
-
-    nsAutoString selectable;
-    SubstituteText(mRows[aRow]->mMatch->mResult, raw, selectable);
-
-    return !selectable.EqualsLiteral("false");
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::IsSelectable(int32_t aRow, nsITreeColumn* aCol, bool* _retval)
 {
-    RefPtr<nsTreeColumn> col = nsTreeColumn::From(aCol);
-    NS_ENSURE_ARG(col);
+    NS_PRECONDITION(aRow >= 0 && aRow < mRows.Count(), "bad index");
+    if (aRow < 0 || aRow >= mRows.Count())
+        return NS_ERROR_INVALID_ARG;
+
+    *_retval = true;
 
-    ErrorResult rv;
-    *_retval = IsSelectable(aRow, *col, rv);
-    return rv.StealNSResult();
+    // Find the <cell> that corresponds to the column we want.
+    nsCOMPtr<nsIContent> cell;
+    GetTemplateActionCellFor(aRow, aCol, getter_AddRefs(cell));
+    if (cell) {
+        nsAutoString raw;
+        cell->GetAttr(kNameSpaceID_None, nsGkAtoms::selectable, raw);
+
+        nsAutoString selectable;
+        SubstituteText(mRows[aRow]->mMatch->mResult, raw, selectable);
+
+        if (selectable.EqualsLiteral("false"))
+            *_retval = false;
+    }
+
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::SetCellValue(int32_t aRow, nsITreeColumn* aCol, const nsAString& aValue)
 {
     NS_ENSURE_ARG_POINTER(aCol);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::SetCellText(int32_t aRow, nsITreeColumn* aCol, const nsAString& aValue)
 {
     NS_ENSURE_ARG_POINTER(aCol);
     return NS_OK;
 }
 
-void
-nsXULTreeBuilder::PerformAction(const nsAString& aAction)
-{
-    uint32_t count = mObservers.Length();
-    for (uint32_t i = 0; i < count; ++i) {
-        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeElementAt(i);
-        if (observer) {
-            observer->OnPerformAction(PromiseFlatString(aAction).get());
-        }
-    }
-}
-
 NS_IMETHODIMP
 nsXULTreeBuilder::PerformAction(const char16_t* aAction)
 {
-    PerformAction(aAction ? nsDependentString(aAction) : EmptyString());
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnPerformAction(aAction);
+    }
 
     return NS_OK;
 }
 
-void
-nsXULTreeBuilder::PerformActionOnRow(const nsAString& aAction, int32_t aRow)
-{
-    uint32_t count = mObservers.Length();
-    for (uint32_t i = 0; i < count; ++i) {
-        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeElementAt(i);
-        if (observer) {
-            observer->OnPerformActionOnRow(PromiseFlatString(aAction).get(), aRow);
-        }
-    }
-}
-
 NS_IMETHODIMP
 nsXULTreeBuilder::PerformActionOnRow(const char16_t* aAction, int32_t aRow)
 {
-    PerformActionOnRow(aAction ? nsDependentString(aAction) : EmptyString(), aRow);
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnPerformActionOnRow(aAction, aRow);
+    }
 
     return NS_OK;
 }
 
-void
-nsXULTreeBuilder::PerformActionOnCell(const nsAString& aAction, int32_t aRow,
-                                      nsTreeColumn& aColumn)
-{
-    nsAutoString id;
-    aColumn.GetId(id);
-
-    uint32_t count = mObservers.Length();
-    for (uint32_t i = 0; i < count; ++i) {
-        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeElementAt(i);
-        if (observer) {
-            observer->OnPerformActionOnCell(PromiseFlatString(aAction).get(), aRow, id.get());
-        }
-    }
-}
-
 NS_IMETHODIMP
 nsXULTreeBuilder::PerformActionOnCell(const char16_t* aAction, int32_t aRow, nsITreeColumn* aCol)
 {
-    RefPtr<nsTreeColumn> col = nsTreeColumn::From(aCol);
-    NS_ENSURE_ARG(col);
+    NS_ENSURE_ARG_POINTER(aCol);
+    nsAutoString id;
+    aCol->GetId(id);
 
-    PerformActionOnCell(aAction ? nsDependentString(aAction) : EmptyString(), aRow, *col);
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnPerformActionOnCell(aAction, aRow, id.get());
+    }
 
     return NS_OK;
 }
 
 
 void
 nsXULTreeBuilder::NodeWillBeDestroyed(const nsINode* aNode)
 {
     nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
     mObservers.Clear();
 
     nsXULTemplateBuilder::NodeWillBeDestroyed(aNode);
 }
 
-bool
+NS_IMETHODIMP
 nsXULTreeBuilder::HasGeneratedContent(nsIRDFResource* aResource,
-                                      const nsAString& aTag,
-                                      ErrorResult& aError)
+                                      nsIAtom* aTag,
+                                      bool* aGenerated)
 {
-    if (!aResource) {
-        aError.Throw(NS_ERROR_INVALID_POINTER);
-        return false;
-    }
+    *aGenerated = false;
+    NS_ENSURE_ARG_POINTER(aResource);
 
-    if (!mRootResult) {
-        return false;
-    }
+    if (!mRootResult)
+        return NS_OK;
 
     nsCOMPtr<nsIRDFResource> rootresource;
-    aError = mRootResult->GetResource(getter_AddRefs(rootresource));
-    if (aError.Failed()) { 
-        return false;
-    }
+    nsresult rv = mRootResult->GetResource(getter_AddRefs(rootresource));
+    if (NS_FAILED(rv))
+        return rv;
 
-    return aResource == rootresource ||
-           mRows.FindByResource(aResource) != mRows.Last();
+    if (aResource == rootresource ||
+        mRows.FindByResource(aResource) != mRows.Last())
+        *aGenerated = true;
+
+    return NS_OK;
 }
 
 bool
 nsXULTreeBuilder::GetInsertionLocations(nsIXULTemplateResult* aResult,
                                         nsCOMArray<nsIContent>** aLocations)
 {
     *aLocations = nullptr;
 
@@ -1377,47 +1151,55 @@ nsXULTreeBuilder::GetTemplateActionRowFo
             }
         }
     }
 
     *aResult = nullptr;
     return NS_OK;
 }
 
-nsIContent*
-nsXULTreeBuilder::GetTemplateActionCellFor(int32_t aRow, nsTreeColumn& aCol)
+nsresult
+nsXULTreeBuilder::GetTemplateActionCellFor(int32_t aRow,
+                                           nsITreeColumn* aCol,
+                                           nsIContent** aResult)
 {
+    *aResult = nullptr;
+
+    if (!aCol) return NS_ERROR_INVALID_ARG;
+
     nsCOMPtr<nsIContent> row;
     GetTemplateActionRowFor(aRow, getter_AddRefs(row));
-    if (!row) {
-        return nullptr;
-    }
-
-    nsCOMPtr<nsIAtom> colAtom(aCol.GetAtom());
-    int32_t colIndex(aCol.GetIndex());
+    if (row) {
+        nsCOMPtr<nsIAtom> colAtom;
+        int32_t colIndex;
+        aCol->GetAtom(getter_AddRefs(colAtom));
+        aCol->GetIndex(&colIndex);
 
-    nsIContent* result = nullptr;
-    uint32_t j = 0;
-    for (nsIContent* child = row->GetFirstChild();
-         child;
-         child = child->GetNextSibling()) {
-        if (child->NodeInfo()->Equals(nsGkAtoms::treecell, kNameSpaceID_XUL)) {
-            if (colAtom &&
-                child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::ref, colAtom,
-                                   eCaseMatters)) {
-                return child;
+        uint32_t j = 0;
+        for (nsIContent* child = row->GetFirstChild();
+             child;
+             child = child->GetNextSibling()) {
+            
+            if (child->NodeInfo()->Equals(nsGkAtoms::treecell,
+                                          kNameSpaceID_XUL)) {
+                if (colAtom &&
+                    child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::ref,
+                                       colAtom, eCaseMatters)) {
+                    *aResult = child;
+                    break;
+                }
+                else if (j == (uint32_t)colIndex)
+                    *aResult = child;
+                j++;
             }
-
-            if (j == (uint32_t)colIndex) {
-                result = child;
-            }
-            ++j;
         }
     }
-    return result;
+    NS_IF_ADDREF(*aResult);
+
+    return NS_OK;
 }
 
 nsresult
 nsXULTreeBuilder::GetResourceFor(int32_t aRow, nsIRDFResource** aResource)
 {
     nsTreeRows::Row& row = *(mRows[aRow]);
     return GetResultResource(row.mMatch->mResult, aResource);
 }
@@ -1834,73 +1616,51 @@ nsXULTreeBuilder::SortSubtree(nsTreeRows
         nsTreeRows::Subtree* child = (*aSubtree)[i].mSubtree;
         if (child)
             SortSubtree(child);
     }
 
     return NS_OK;
 }
 
-bool
-nsXULTreeBuilder::CanDrop(int32_t aRow, int32_t aOrientation,
-                          DataTransfer* aDataTransfer, ErrorResult& aError)
-{
-    uint32_t count = mObservers.Length();
-    for (uint32_t i = 0; i < count; ++i) {
-        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeElementAt(i);
-        if (observer) {
-            bool canDrop = false;
-            observer->CanDrop(aRow, aOrientation, aDataTransfer, &canDrop);
-            if (canDrop) {
-                return true;
-            }
-        }
-    }
-    
-    return false;
-}
 
 NS_IMETHODIMP
 nsXULTreeBuilder::CanDrop(int32_t index, int32_t orientation,
                           nsIDOMDataTransfer* dataTransfer, bool *_retval)
 {
-    ErrorResult rv;
-    *_retval = CanDrop(index, orientation, DataTransfer::Cast(dataTransfer),
-                       rv);
-    return rv.StealNSResult();
-}
-
-void
-nsXULTreeBuilder::Drop(int32_t aRow, int32_t aOrientation,
-                       DataTransfer* aDataTransfer, ErrorResult& aError)
-{
-    uint32_t count = mObservers.Length();
+    *_retval = false;
+    uint32_t count = mObservers.Count();
     for (uint32_t i = 0; i < count; ++i) {
-        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeElementAt(i);
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
         if (observer) {
-            bool canDrop = false;
-            observer->CanDrop(aRow, aOrientation, aDataTransfer, &canDrop);
-            if (canDrop)
-                observer->OnDrop(aRow, aOrientation, aDataTransfer);
+            observer->CanDrop(index, orientation, dataTransfer, _retval);
+            if (*_retval)
+                break;
         }
     }
+
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::Drop(int32_t row, int32_t orient, nsIDOMDataTransfer* dataTransfer)
 {
-    ErrorResult rv;
-    Drop(row, orient, DataTransfer::Cast(dataTransfer), rv);
-    return rv.StealNSResult();
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer) {
+            bool canDrop = false;
+            observer->CanDrop(row, orient, dataTransfer, &canDrop);
+            if (canDrop)
+                observer->OnDrop(row, orient, dataTransfer);
+        }
+    }
+
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::IsSorted(bool *_retval)
 {
   *_retval = (mSortVariable != nullptr);
   return NS_OK;
 }
 
-bool
-nsXULTreeBuilder::IsValidRowIndex(int32_t aRowIndex)
-{
-    return aRowIndex >= 0 && aRowIndex < int32_t(mRows.Count());
-}
--- a/dom/xul/templates/nsXULTreeBuilder.h
+++ b/dom/xul/templates/nsXULTreeBuilder.h
@@ -32,119 +32,38 @@ class XULTreeBuilderObserver;
  * A XUL template builder that serves as an tree view, allowing
  * (pretty much) arbitrary RDF to be presented in an tree.
  */
 class nsXULTreeBuilder : public nsXULTemplateBuilder,
                          public nsIXULTreeBuilder,
                          public nsINativeTreeView
 {
 public:
-    explicit nsXULTreeBuilder(Element* aElement);
-
     // nsISupports
     NS_DECL_ISUPPORTS_INHERITED
-    NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeBuilder,
-                                             nsXULTemplateBuilder)
-
-    virtual JSObject* WrapObject(JSContext* aCx,
-                                 JS::Handle<JSObject*> aGivenProto) override;
-
-    already_AddRefed<nsIRDFResource>
-      GetResourceAtIndex(int32_t aIndex, mozilla::ErrorResult& aError);
-    int32_t GetIndexOfResource(nsIRDFResource* aResource,
-                               mozilla::ErrorResult& aError);
-    void AddObserver(mozilla::dom::XULTreeBuilderObserver& aObserver);
-    void RemoveObserver(mozilla::dom::XULTreeBuilderObserver& aObserver);
-    void Sort(Element&);
-
-    int32_t RowCount()
-    {
-        return mRows.Count();
-    }
-    nsITreeSelection* GetSelection()
-    {
-        return mSelection;
-    }
-    void SetSelection(nsITreeSelection* aSelection,
-                      mozilla::ErrorResult& aError);
-    void GetRowProperties(int32_t aRow, nsAString& aProperties,
-                          mozilla::ErrorResult& aError);
-    void GetCellProperties(int32_t aRow, nsTreeColumn& aColumn,
-                           nsAString& aProperties, mozilla::ErrorResult& aError);
-    void GetColumnProperties(nsTreeColumn& aColumn, nsAString& aProperties)
-    {
-    }
-    bool IsContainer(int32_t aRow, mozilla::ErrorResult& aError);
-    bool IsContainerOpen(int32_t aRow, mozilla::ErrorResult& aError);
-    bool IsContainerEmpty(int32_t aRow, mozilla::ErrorResult& aError);
-    bool IsSeparator(int32_t aRow, mozilla::ErrorResult& aError);
-    bool IsSorted()
-    {
-        return mSortVariable != nullptr;
-    }
-    bool CanDrop(int32_t aRow, int32_t aOrientation,
-                 mozilla::dom::DataTransfer* aDataTransfer,
-                 mozilla::ErrorResult& aError);
-    void Drop(int32_t aRow, int32_t aOrientation,
-              mozilla::dom::DataTransfer* aDataTransfer,
-              mozilla::ErrorResult& aError);
-    int32_t GetParentIndex(int32_t aRow, mozilla::ErrorResult& aError);
-    bool HasNextSibling(int32_t aRow, int32_t aAfterIndex,
-                        mozilla::ErrorResult& aError);
-    int32_t GetLevel(int32_t aRow, mozilla::ErrorResult& aError);
-    void GetImageSrc(int32_t aRow, nsTreeColumn& aColumn, nsAString& aSrc,
-                     mozilla::ErrorResult& aError);
-    int32_t GetProgressMode(int32_t aRow, nsTreeColumn& aColumn,
-                            mozilla::ErrorResult& aError);
-    void GetCellValue(int32_t aRow, nsTreeColumn& aColumn, nsAString& aValue,
-                      mozilla::ErrorResult& aError);
-    void GetCellText(int32_t aRow, nsTreeColumn& aColumn, nsAString& aText,
-                     mozilla::ErrorResult& aError);
-    void SetTree(mozilla::dom::TreeBoxObject* aTree,
-                 mozilla::ErrorResult& aError);
-    void ToggleOpenState(int32_t aRow, mozilla::ErrorResult& aError);
-    void CycleHeader(nsTreeColumn& aColumn, mozilla::ErrorResult& aError);
-    // XPCOM SelectionChanged() is OK
-    void CycleCell(int32_t aRow, nsTreeColumn& aColumn);
-    bool IsEditable(int32_t aRow, nsTreeColumn& aColumn,
-                    mozilla::ErrorResult& aError);
-    bool IsSelectable(int32_t aRow, nsTreeColumn& aColumn,
-                      mozilla::ErrorResult& aError);
-    void SetCellValue(int32_t aRow, nsTreeColumn& aColumn,
-                      const nsAString& aValue, mozilla::ErrorResult& aError)
-    {
-    }
-    void SetCellText(int32_t aRow, nsTreeColumn& aColumn,
-                      const nsAString& aText, mozilla::ErrorResult& aError)
-    {
-    }
-    void PerformAction(const nsAString& aAction);
-    void PerformActionOnRow(const nsAString& aAction, int32_t aRow);
-    void PerformActionOnCell(const nsAString& aAction, int32_t aRow,
-                             nsTreeColumn& aColumn);
-
-    using nsIXULTemplateBuilder::HasGeneratedContent;
-    virtual bool HasGeneratedContent(nsIRDFResource* aResource,
-                                     const nsAString& aTag,
-                                     mozilla::ErrorResult& aError) override;
+    NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder)
 
     // nsIXULTreeBuilder
     NS_DECL_NSIXULTREEBUILDER
 
     // nsITreeView
     NS_DECL_NSITREEVIEW
     // nsINativeTreeView: Untrusted code can use us
     NS_IMETHOD EnsureNative() override { return NS_OK; }
 
     // nsIMutationObserver
     NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
 
 protected:
+    friend nsresult
+    NS_NewXULTreeBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult);
+
     friend struct ResultComparator;
 
+    nsXULTreeBuilder();
     ~nsXULTreeBuilder();
 
     /**
      * Uninitialize the template builder
      */
     virtual void Uninit(bool aIsFinal) override;
 
     /**
@@ -162,18 +81,18 @@ protected:
      */
     nsresult
     GetTemplateActionRowFor(int32_t aRow, nsIContent** aResult);
 
     /**
      * Given a row and a column ID, use the row's match to figure out
      * the appropriate <treecell> in the rule's <action>.
      */
-    nsIContent*
-    GetTemplateActionCellFor(int32_t aRow, nsTreeColumn& aCol);
+    nsresult
+    GetTemplateActionCellFor(int32_t aRow, nsITreeColumn* aCol, nsIContent** aResult);
 
     /**
      * Return the resource corresponding to a row in the tree.
      */
     nsresult
     GetResourceFor(int32_t aRow, nsIRDFResource** aResource);
 
     /**
@@ -234,16 +153,21 @@ protected:
 
     /**
      * Sort the specified subtree, and recursively sort any subtrees
      * beneath it.
      */
     nsresult
     SortSubtree(nsTreeRows::Subtree* aSubtree);
 
+    NS_IMETHOD
+    HasGeneratedContent(nsIRDFResource* aResource,
+                        nsIAtom* aTag,
+                        bool* aGenerated) override;
+
     // GetInsertionLocations, ReplaceMatch and SynchronizeResult are inherited
     // from nsXULTemplateBuilder
 
     /**
      * Return true if the result can be inserted into the template as a new
      * row.
      */
     bool
@@ -260,18 +184,16 @@ protected:
                  void* aContext) override;
 
     /**
      * Implement match synchronization
      */
     virtual nsresult
     SynchronizeResult(nsIXULTemplateResult* aResult) override;
 
-    bool IsValidRowIndex(int32_t aRowIndex);
-
     /**
      * The tree's box object, used to communicate with the front-end.
      */
     nsCOMPtr<nsITreeBoxObject> mBoxObject;
 
     /**
      * The tree's selection object.
      */
@@ -306,17 +228,17 @@ protected:
     /*
      * Sort hints (compare case, etc)
      */
     uint32_t mSortHints;
 
     /** 
      * The builder observers.
      */
-    nsTArray<nsCOMPtr<nsIXULTreeBuilderObserver>> mObservers;
+    nsCOMArray<nsIXULTreeBuilderObserver> mObservers;
 
     /*
      * XUL store for holding open container state
      */
     nsCOMPtr<nsIXULStore> mLocalStore;
 };
 
 #endif // nsXULTreeBuilder_h__
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -151,16 +151,22 @@ class nsIDocumentLoaderFactory;
 
 #include "inDeepTreeWalker.h"
 #include "inCSSValueSearch.h"
 #include "inDOMUtils.h"
 
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
 #include "nsIXULSortService.h"
+
+nsresult
+NS_NewXULContentBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult);
+
+nsresult
+NS_NewXULTreeBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 #endif
 
 static void Shutdown();
 
 #include "nsGeolocation.h"
 #include "nsDeviceSensors.h"
 #include "mozilla/dom/nsContentSecurityManager.h"
 #include "mozilla/dom/nsCSPService.h"
@@ -455,16 +461,18 @@ MAKE_CTOR(CreateTextEncoder,            
 MAKE_CTOR(CreateHTMLCopyTextEncoder,      nsIDocumentEncoder,          NS_NewHTMLCopyTextEncoder)
 MAKE_CTOR(CreateXMLContentSerializer,     nsIContentSerializer,        NS_NewXMLContentSerializer)
 MAKE_CTOR(CreateHTMLContentSerializer,    nsIContentSerializer,        NS_NewHTMLContentSerializer)
 MAKE_CTOR(CreateXHTMLContentSerializer,   nsIContentSerializer,        NS_NewXHTMLContentSerializer)
 MAKE_CTOR(CreatePlainTextSerializer,      nsIContentSerializer,        NS_NewPlainTextSerializer)
 MAKE_CTOR(CreateContentPolicy,            nsIContentPolicy,            NS_NewContentPolicy)
 #ifdef MOZ_XUL
 MAKE_CTOR(CreateXULSortService,           nsIXULSortService,           NS_NewXULSortService)
+// NS_NewXULContentBuilder
+// NS_NewXULTreeBuilder
 MAKE_CTOR(CreateXULDocument,              nsIXULDocument,              NS_NewXULDocument)
 // NS_NewXULControllers
 #endif
 MAKE_CTOR(CreateContentDLF,               nsIDocumentLoaderFactory,    NS_NewContentDocumentLoaderFactory)
 MAKE_CTOR(CreateEventListenerService,     nsIEventListenerService,     NS_NewEventListenerService)
 MAKE_CTOR(CreateGlobalMessageManager,     nsIMessageBroadcaster,       NS_NewGlobalMessageManager)
 MAKE_CTOR(CreateParentMessageManager,     nsIMessageBroadcaster,       NS_NewParentProcessMessageManager)
 MAKE_CTOR(CreateChildMessageManager,      nsISyncMessageSender,        NS_NewChildProcessMessageManager)
@@ -617,16 +625,18 @@ NS_DEFINE_NAMED_CID(NS_PLAINTEXTSERIALIZ
 NS_DEFINE_NAMED_CID(NS_PARSERUTILS_CID);
 NS_DEFINE_NAMED_CID(NS_SCRIPTABLEUNESCAPEHTML_CID);
 NS_DEFINE_NAMED_CID(NS_CONTENTPOLICY_CID);
 NS_DEFINE_NAMED_CID(NS_DATADOCUMENTCONTENTPOLICY_CID);
 NS_DEFINE_NAMED_CID(NS_NODATAPROTOCOLCONTENTPOLICY_CID);
 NS_DEFINE_NAMED_CID(NS_XULCONTROLLERS_CID);
 #ifdef MOZ_XUL
 NS_DEFINE_NAMED_CID(NS_XULSORTSERVICE_CID);
+NS_DEFINE_NAMED_CID(NS_XULTEMPLATEBUILDER_CID);
+NS_DEFINE_NAMED_CID(NS_XULTREEBUILDER_CID);
 NS_DEFINE_NAMED_CID(NS_XULDOCUMENT_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_CONTENT_DOCUMENT_LOADER_FACTORY_CID);
 NS_DEFINE_NAMED_CID(NS_JSPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_JSURI_CID);
 NS_DEFINE_NAMED_CID(NS_WINDOWCOMMANDTABLE_CID);
 NS_DEFINE_NAMED_CID(NS_WINDOWCONTROLLER_CID);
 NS_DEFINE_NAMED_CID(NS_PLUGINDOCLOADERFACTORY_CID);
@@ -880,16 +890,18 @@ static const mozilla::Module::CIDEntry k
   { &kNS_PARSERUTILS_CID, false, nullptr, nsParserUtilsConstructor },
   { &kNS_SCRIPTABLEUNESCAPEHTML_CID, false, nullptr, nsParserUtilsConstructor },
   { &kNS_CONTENTPOLICY_CID, false, nullptr, CreateContentPolicy },
   { &kNS_DATADOCUMENTCONTENTPOLICY_CID, false, nullptr, nsDataDocumentContentPolicyConstructor },
   { &kNS_NODATAPROTOCOLCONTENTPOLICY_CID, false, nullptr, nsNoDataProtocolContentPolicyConstructor },
   { &kNS_XULCONTROLLERS_CID, false, nullptr, NS_NewXULControllers },
 #ifdef MOZ_XUL
   { &kNS_XULSORTSERVICE_CID, false, nullptr, CreateXULSortService },
+  { &kNS_XULTEMPLATEBUILDER_CID, false, nullptr, NS_NewXULContentBuilder },
+  { &kNS_XULTREEBUILDER_CID, false, nullptr, NS_NewXULTreeBuilder },
   { &kNS_XULDOCUMENT_CID, false, nullptr, CreateXULDocument },
 #endif
   { &kNS_CONTENT_DOCUMENT_LOADER_FACTORY_CID, false, nullptr, CreateContentDLF },
   { &kNS_JSPROTOCOLHANDLER_CID, false, nullptr, nsJSProtocolHandler::Create },
   { &kNS_JSURI_CID, false, nullptr, nsJSURIConstructor },
   { &kNS_WINDOWCOMMANDTABLE_CID, false, nullptr, CreateWindowCommandTableConstructor },
   { &kNS_WINDOWCONTROLLER_CID, false, nullptr, CreateWindowControllerWithSingletonCommandTable },
   { &kNS_PLUGINDOCLOADERFACTORY_CID, false, nullptr, CreateContentDLF },
@@ -1014,16 +1026,18 @@ static const mozilla::Module::ContractID
   { NS_PARSERUTILS_CONTRACTID, &kNS_PARSERUTILS_CID },
   { NS_SCRIPTABLEUNESCAPEHTML_CONTRACTID, &kNS_SCRIPTABLEUNESCAPEHTML_CID },
   { NS_CONTENTPOLICY_CONTRACTID, &kNS_CONTENTPOLICY_CID },
   { NS_DATADOCUMENTCONTENTPOLICY_CONTRACTID, &kNS_DATADOCUMENTCONTENTPOLICY_CID },
   { NS_NODATAPROTOCOLCONTENTPOLICY_CONTRACTID, &kNS_NODATAPROTOCOLCONTENTPOLICY_CID },
   { "@mozilla.org/xul/xul-controllers;1", &kNS_XULCONTROLLERS_CID },
 #ifdef MOZ_XUL
   { "@mozilla.org/xul/xul-sort-service;1", &kNS_XULSORTSERVICE_CID },
+  { "@mozilla.org/xul/xul-template-builder;1", &kNS_XULTEMPLATEBUILDER_CID },
+  { "@mozilla.org/xul/xul-tree-builder;1", &kNS_XULTREEBUILDER_CID },
   { "@mozilla.org/xul/xul-document;1", &kNS_XULDOCUMENT_CID },
 #endif
   { CONTENT_DLF_CONTRACTID, &kNS_CONTENT_DOCUMENT_LOADER_FACTORY_CID },
   { NS_JSPROTOCOLHANDLER_CONTRACTID, &kNS_JSPROTOCOLHANDLER_CID },
   { NS_WINDOWCONTROLLER_CONTRACTID, &kNS_WINDOWCONTROLLER_CID },
   { PLUGIN_DLF_CONTRACTID, &kNS_PLUGINDOCLOADERFACTORY_CID },
   { NS_STYLESHEETSERVICE_CONTRACTID, &kNS_STYLESHEETSERVICE_CID },
   { TRANSFORMIIX_XSLT_PROCESSOR_CONTRACTID, &kTRANSFORMIIX_XSLT_PROCESSOR_CID },
--- a/layout/xul/tree/nsTreeColumns.h
+++ b/layout/xul/tree/nsTreeColumns.h
@@ -6,17 +6,16 @@
 #ifndef nsTreeColumns_h__
 #define nsTreeColumns_h__
 
 #include "nsITreeColumns.h"
 #include "nsITreeBoxObject.h"
 #include "mozilla/Attributes.h"
 #include "nsCoord.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsQueryObject.h"
 #include "nsWrapperCache.h"
 #include "nsString.h"
 
 class nsTreeBodyFrame;
 class nsTreeColumns;
 class nsIFrame;
 class nsIContent;
 struct nsRect;
@@ -42,22 +41,16 @@ class TreeBoxObject;
 class nsTreeColumn final : public nsITreeColumn
                          , public nsWrapperCache
 {
 public:
   nsTreeColumn(nsTreeColumns* aColumns, nsIContent* aContent);
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_TREECOLUMN_IMPL_CID)
 
-  static already_AddRefed<nsTreeColumn> From(nsITreeColumn* aColumn)
-  {
-    RefPtr<nsTreeColumn> col = do_QueryObject(aColumn);
-    return col.forget();
-  }
-
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsTreeColumn)
   NS_DECL_NSITREECOLUMN
 
   // WebIDL
   nsIContent* GetParentObject() const;
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
@@ -100,22 +93,20 @@ protected:
                    nsRect* aResult);
 
   nsresult GetXInTwips(nsTreeBodyFrame* aBodyFrame, nscoord* aResult);
   nsresult GetWidthInTwips(nsTreeBodyFrame* aBodyFrame, nscoord* aResult);
 
   void SetColumns(nsTreeColumns* aColumns) { mColumns = aColumns; }
 
   const nsAString& GetId() { return mId; }
+  nsIAtom* GetAtom() { return mAtom; }
 
-public:
-  nsIAtom* GetAtom() { return mAtom; }
   int32_t GetIndex() { return mIndex; }
 
-protected:
   bool IsPrimary() { return mIsPrimary; }
   bool IsCycler() { return mIsCycler; }
   bool IsEditable() { return mIsEditable; }
   bool IsSelectable() { return mIsSelectable; }
   bool Overflow() { return mOverflow; }
 
   int16_t GetType() { return mType; }