Merge m-c to birch.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 31 Jul 2013 08:54:33 -0400
changeset 153033 ee5c1138cbfd762099377bbe680cbb99c855742f
parent 153032 523c7b92d52fea9cf0a27af4b012a3a2d14aacf5 (current diff)
parent 153015 ffd57aa81b5f370a67ae0c0bbd539d6d228154ed (diff)
child 153034 89ce7c357c1cd55929ca1e62017c1179cf5da738
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone25.0a1
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
Merge m-c to birch.
layout/base/nsStyleConsts.h
layout/generic/nsTextFrameThebes.cpp
toolkit/crashreporter/breakpad-patches/12-sht-arm-exidx-define.patch
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -1031,16 +1031,17 @@ SourceScripts.prototype = {
   /**
    * Handler for the debugger client's 'blackboxchange' notification.
    */
   _onBlackBoxChange: function (aEvent, { url, isBlackBoxed }) {
     const item = DebuggerView.Sources.getItemByValue(url);
     if (item) {
       DebuggerView.Sources.callMethod("checkItem", item.target, !isBlackBoxed);
     }
+    DebuggerView.Sources.maybeShowBlackBoxMessage();
   },
 
   /**
    * Set the black boxed status of the given source.
    *
    * @param Object aSource
    *        The source form.
    * @param bool aBlackBoxFlag
--- a/browser/devtools/debugger/debugger-panes.js
+++ b/browser/devtools/debugger/debugger-panes.js
@@ -14,16 +14,17 @@ function SourcesView() {
   this._onEditorLoad = this._onEditorLoad.bind(this);
   this._onEditorUnload = this._onEditorUnload.bind(this);
   this._onEditorSelection = this._onEditorSelection.bind(this);
   this._onEditorContextMenu = this._onEditorContextMenu.bind(this);
   this._onSourceSelect = this._onSourceSelect.bind(this);
   this._onSourceClick = this._onSourceClick.bind(this);
   this._onBreakpointRemoved = this._onBreakpointRemoved.bind(this);
   this._onSourceCheck = this._onSourceCheck.bind(this);
+  this._onStopBlackBoxing = this._onStopBlackBoxing.bind(this);
   this._onBreakpointClick = this._onBreakpointClick.bind(this);
   this._onBreakpointCheckboxClick = this._onBreakpointCheckboxClick.bind(this);
   this._onConditionalPopupShowing = this._onConditionalPopupShowing.bind(this);
   this._onConditionalPopupShown = this._onConditionalPopupShown.bind(this);
   this._onConditionalPopupHiding = this._onConditionalPopupHiding.bind(this);
   this._onConditionalTextboxInput = this._onConditionalTextboxInput.bind(this);
   this._onConditionalTextboxKeyPress = this._onConditionalTextboxKeyPress.bind(this);
 }
@@ -43,22 +44,25 @@ SourcesView.prototype = Heritage.extend(
     this.unavailableText = L10N.getStr("noMatchingSourcesText");
     this._blackBoxCheckboxTooltip = L10N.getStr("blackBoxCheckboxTooltip");
 
     this._commandset = document.getElementById("debuggerCommands");
     this._popupset = document.getElementById("debuggerPopupset");
     this._cmPopup = document.getElementById("sourceEditorContextMenu");
     this._cbPanel = document.getElementById("conditional-breakpoint-panel");
     this._cbTextbox = document.getElementById("conditional-breakpoint-panel-textbox");
+    this._editorDeck = document.getElementById("editor-deck");
+    this._stopBlackBoxButton = document.getElementById("black-boxed-message-button");
 
     window.addEventListener("Debugger:EditorLoaded", this._onEditorLoad, false);
     window.addEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
     this.widget.addEventListener("select", this._onSourceSelect, false);
     this.widget.addEventListener("click", this._onSourceClick, false);
     this.widget.addEventListener("check", this._onSourceCheck, false);
+    this._stopBlackBoxButton.addEventListener("click", this._onStopBlackBoxing, false);
     this._cbPanel.addEventListener("popupshowing", this._onConditionalPopupShowing, false);
     this._cbPanel.addEventListener("popupshown", this._onConditionalPopupShown, false);
     this._cbPanel.addEventListener("popuphiding", this._onConditionalPopupHiding, false);
     this._cbTextbox.addEventListener("input", this._onConditionalTextboxInput, false);
     this._cbTextbox.addEventListener("keypress", this._onConditionalTextboxKeyPress, false);
 
     this.autoFocusOnSelection = false;
 
@@ -72,16 +76,17 @@ SourcesView.prototype = Heritage.extend(
   destroy: function() {
     dumpn("Destroying the SourcesView");
 
     window.removeEventListener("Debugger:EditorLoaded", this._onEditorLoad, false);
     window.removeEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
     this.widget.removeEventListener("select", this._onSourceSelect, false);
     this.widget.removeEventListener("click", this._onSourceClick, false);
     this.widget.removeEventListener("check", this._onSourceCheck, false);
+    this._stopBlackBoxButton.removeEventListener("click", this._onStopBlackBoxing, false);
     this._cbPanel.removeEventListener("popupshowing", this._onConditionalPopupShowing, false);
     this._cbPanel.removeEventListener("popupshowing", this._onConditionalPopupShown, false);
     this._cbPanel.removeEventListener("popuphiding", this._onConditionalPopupHiding, false);
     this._cbTextbox.removeEventListener("input", this._onConditionalTextboxInput, false);
     this._cbTextbox.removeEventListener("keypress", this._onConditionalTextboxKeyPress, false);
   },
 
   /**
@@ -633,16 +638,28 @@ SourcesView.prototype = Heritage.extend(
       return;
     }
     // The container is not empty and an actual item was selected.
     let selectedSource = sourceItem.attachment.source;
 
     if (DebuggerView.editorSource != selectedSource) {
       DebuggerView.editorSource = selectedSource;
     }
+
+    this.maybeShowBlackBoxMessage();
+  },
+
+  /**
+   * Show or hide the black box message vs. source editor depending on if the
+   * selected source is black boxed or not.
+   */
+  maybeShowBlackBoxMessage: function () {
+    const source = DebuggerController.activeThread.source(
+      DebuggerView.editorSource);
+    this._editorDeck.selectedIndex = source.isBlackBoxed ? 1 : 0;
   },
 
   /**
    * The click listener for the sources container.
    */
   _onSourceClick: function() {
     // Use this container as a filtering target.
     DebuggerView.Filtering.target = this;
@@ -652,16 +669,24 @@ SourcesView.prototype = Heritage.extend(
    * The check listener for the sources container.
    */
   _onSourceCheck: function({ detail: { checked }, target }) {
     let item = this.getItemForElement(target);
     DebuggerController.SourceScripts.blackBox(item.attachment.source, !checked);
   },
 
   /**
+   * The click listener for the stop black boxing button.
+   */
+  _onStopBlackBoxing: function() {
+    DebuggerController.SourceScripts.blackBox(DebuggerView.editorSource,
+                                              false);
+  },
+
+  /**
    * The click listener for a breakpoint container.
    */
   _onBreakpointClick: function(e) {
     let sourceItem = this.getItemForElement(e.target);
     let breakpointItem = this.getItemForElement.call(sourceItem, e.target);
     let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
 
     let breakpointClient = DebuggerController.Breakpoints.getBreakpoint(url, line);
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -27,16 +27,18 @@
   <script type="text/javascript" src="debugger-view.js"/>
   <script type="text/javascript" src="debugger-toolbar.js"/>
   <script type="text/javascript" src="debugger-panes.js"/>
 
   <commandset id="editMenuCommands"/>
   <commandset id="sourceEditorCommands"/>
 
   <commandset id="debuggerCommands">
+    <command id="unBlackBoxButton"
+             oncommand="DebuggerView.Sources._onStopBlackBoxing()"/>
     <command id="nextSourceCommand"
              oncommand="DebuggerView.Sources.selectNextItem()"/>
     <command id="prevSourceCommand"
              oncommand="DebuggerView.Sources.selectPrevItem()"/>
     <command id="resumeCommand"
              oncommand="DebuggerView.Toolbar._onResumePressed()"/>
     <command id="stepOverCommand"
              oncommand="DebuggerView.Toolbar._onStepOverPressed()"/>
@@ -288,17 +290,29 @@
     <vbox flex="1">
       <scrollbox id="globalsearch" orient="vertical" hidden="true"/>
       <splitter class="devtools-horizontal-splitter" hidden="true"/>
       <hbox flex="1">
         <vbox id="sources-pane">
           <vbox id="sources" flex="1"/>
         </vbox>
         <splitter class="devtools-side-splitter"/>
-        <vbox id="editor" flex="1"/>
+        <deck id="editor-deck" flex="1" selectedIndex="0">
+          <vbox id="editor" />
+          <vbox id="black-boxed-message" align="center">
+            <label id="black-boxed-message-label">
+              &debuggerUI.blackBoxMessage.label;
+            </label>
+            <button id="black-boxed-message-button"
+                    class="devtools-toolbarbutton"
+                    label="&debuggerUI.blackBoxMessage.unBlackBoxButton;"
+                    image="chrome://browser/skin/devtools/blackBoxMessageEye.png"
+                    command="unBlackBoxCommand"/>
+          </vbox>
+        </deck>
         <splitter class="devtools-side-splitter"/>
         <vbox id="instruments-pane" hidden="true">
           <vbox id="expressions"/>
           <splitter class="devtools-horizontal-splitter"/>
           <vbox id="variables" flex="1"/>
         </vbox>
       </hbox>
     </vbox>
--- a/browser/devtools/debugger/test/Makefile.in
+++ b/browser/devtools/debugger/test/Makefile.in
@@ -11,16 +11,17 @@ relativesrcdir  = @relativesrcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_BROWSER_TESTS = \
 	browser_dbg_aaa_run_first_leaktest.js \
 	browser_dbg_blackboxing-01.js \
 	browser_dbg_blackboxing-02.js \
 	browser_dbg_blackboxing-03.js \
 	browser_dbg_blackboxing-04.js \
+	browser_dbg_blackboxing-05.js \
 	browser_dbg_clean-exit.js \
 	browser_dbg_cmd.js \
 	browser_dbg_cmd_blackbox.js \
 	browser_dbg_cmd_break.js \
 	browser_dbg_debuggerstatement.js \
 	browser_dbg_listtabs-01.js \
 	browser_dbg_listtabs-02.js \
 	browser_dbg_tabactor-01.js \
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_blackboxing-05.js
@@ -0,0 +1,86 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test that we get a stack frame for each black boxed source, not a single one
+ * for all of them.
+ */
+
+const TAB_URL = EXAMPLE_URL + "binary_search.html";
+
+var gPane = null;
+var gTab = null;
+var gDebuggee = null;
+var gDebugger = null;
+
+function test()
+{
+  let scriptShown = false;
+  let framesAdded = false;
+  let resumed = false;
+  let testStarted = false;
+
+  debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
+    resumed = true;
+    gTab = aTab;
+    gDebuggee = aDebuggee;
+    gPane = aPane;
+    gDebugger = gPane.panelWin;
+
+    once(gDebugger, "Debugger:SourceShown", testSourceEditorShown);
+  });
+}
+
+function testSourceEditorShown() {
+  const deck = gDebugger.document.getElementById("editor-deck");
+  is(deck.selectedIndex, "0",
+     "The first item in the deck should be selected (the source editor)");
+  blackBoxSource();
+}
+
+function blackBoxSource() {
+  const { activeThread } = gDebugger.DebuggerController;
+  activeThread.addOneTimeListener("blackboxchange", testBlackBoxMessageShown);
+  getBlackBoxCheckbox().click();
+}
+
+function testBlackBoxMessageShown() {
+  const deck = gDebugger.document.getElementById("editor-deck");
+  is(deck.selectedIndex, "1",
+     "The second item in the deck should be selected (the black box message)");
+  clickStopBlackBoxingButton();
+}
+
+function clickStopBlackBoxingButton() {
+  const button = gDebugger.document.getElementById("black-boxed-message-button");
+  const { activeThread } = gDebugger.DebuggerController;
+  activeThread.addOneTimeListener("blackboxchange", testSourceEditorShownAgain);
+  button.click();
+}
+
+function testSourceEditorShownAgain() {
+  const deck = gDebugger.document.getElementById("editor-deck");
+  is(deck.selectedIndex, "0",
+     "The first item in the deck should be selected again (the source editor)");
+  closeDebuggerAndFinish();
+}
+
+function getBlackBoxCheckbox() {
+  return gDebugger.document.querySelector(
+    ".side-menu-widget-item .side-menu-widget-item-checkbox");
+}
+
+function once(target, event, callback) {
+  target.addEventListener(event, function _listener(...args) {
+    target.removeEventListener(event, _listener, false);
+    callback.apply(null, args);
+  }, false);
+}
+
+registerCleanupFunction(function() {
+  removeTab(gTab);
+  gPane = null;
+  gTab = null;
+  gDebuggee = null;
+  gDebugger = null;
+});
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -414,18 +414,17 @@ var Scratchpad = {
 
     this.execute().then(([aString, aError, aResult]) => {
       let resolve = () => deferred.resolve([aString, aError, aResult]);
 
       if (aError) {
         this.writeAsErrorComment(aError.exception).then(resolve, reject);
       }
       else if (VariablesView.isPrimitive({ value: aResult })) {
-        this.writeAsComment(aResult.type || aResult);
-        resolve();
+        this._writePrimitiveAsComment(aResult).then(resolve, reject);
       }
       else {
         this.deselect();
         this.sidebar.open(aString, aResult).then(resolve, reject);
       }
     }, reject);
 
     return deferred.promise;
@@ -483,23 +482,23 @@ var Scratchpad = {
 
     this.execute().then(([aString, aError, aResult]) => {
       let resolve = () => deferred.resolve([aString, aError, aResult]);
 
       if (aError) {
         this.writeAsErrorComment(aError.exception).then(resolve, reject);
       }
       else if (VariablesView.isPrimitive({ value: aResult })) {
-        this.writeAsComment(aResult.type || aResult);
-        resolve();
+        this._writePrimitiveAsComment(aResult).then(resolve, reject);
       }
       else {
         let gripClient = new GripClient(this.debuggerClient, aResult);
         gripClient.getDisplayString(aResponse => {
           if (aResponse.error) {
+            reportError("display", aResponse);
             reject(aResponse);
           }
           else {
             let string = aResponse.displayString;
             if (string && string.type == "null") {
               string = "Exception: " +
                        this.strings.GetStringFromName("stringConversionFailed");
             }
@@ -509,16 +508,51 @@ var Scratchpad = {
         });
       }
     }, reject);
 
     return deferred.promise;
   },
 
   /**
+   * Writes out a primitive value as a comment. This handles values which are
+   * to be printed directly (number, string) as well as grips to values
+   * (null, undefined, longString).
+   *
+   * @param any aValue
+   *        The value to print.
+   * @return Promise
+   *         The promise that resolves after the value has been printed.
+   */
+  _writePrimitiveAsComment: function SP__writePrimitiveAsComment(aValue)
+  {
+    let deferred = promise.defer();
+
+    if (aValue.type == "longString") {
+      let client = this.webConsoleClient;
+      client.longString(aValue).substring(0, aValue.length, aResponse => {
+        if (aResponse.error) {
+          reportError("display", aResponse);
+          deferred.reject(aResponse);
+        }
+        else {
+          deferred.resolve(aResponse.substring);
+        }
+      });
+    }
+    else {
+      deferred.resolve(aValue.type || aValue);
+    }
+
+    return deferred.promise.then(aComment => {
+      this.writeAsComment(aComment);
+    });
+  },
+
+  /**
    * Write out a value at the next line from the current insertion point.
    * The comment block will always be preceded by a newline character.
    * @param object aValue
    *        The Object to write out as a string
    */
   writeAsComment: function SP_writeAsComment(aValue)
   {
     let selection = this.getSelectionRange();
--- a/browser/devtools/scratchpad/test/Makefile.in
+++ b/browser/devtools/scratchpad/test/Makefile.in
@@ -32,14 +32,15 @@ MOCHITEST_BROWSER_FILES = \
 		browser_scratchpad_bug_650760_help_key.js \
 		browser_scratchpad_bug_651942_recent_files.js \
 		browser_scratchpad_bug756681_display_non_error_exceptions.js \
 		browser_scratchpad_bug_751744_revert_to_saved.js \
 		browser_scratchpad_bug740948_reload_and_run.js \
 		browser_scratchpad_bug_661762_wrong_window_focus.js \
 		browser_scratchpad_bug_644413_modeline.js \
 		browser_scratchpad_bug807924_cannot_convert_to_string.js \
+		browser_scratchpad_long_string.js \
 		head.js \
 
 # Disable test due to bug 807234 becoming basically permanent
 #		browser_scratchpad_bug_653427_confirm_close.js \
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_long_string.js
@@ -0,0 +1,30 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test()
+{
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+    gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+    openScratchpad(runTests);
+  }, true);
+
+  content.location = "data:text/html;charset=utf8,<p>test long string in Scratchpad</p>";
+}
+
+function runTests()
+{
+  let sp = gScratchpadWindow.Scratchpad;
+
+  sp.setText("'0'.repeat(10000)");
+
+  sp.display().then(() => {
+    is(sp.getText(), "'0'.repeat(10000)\n" +
+                     "/*\n" + "0".repeat(10000) + "\n*/",
+       "display()ing a long string works");
+    finish();
+  });
+}
--- a/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
@@ -14,16 +14,26 @@
 <!-- LOCALIZATION NOTE (debuggerUI.closeButton.tooltip): This is the tooltip for
   -  the button that closes the debugger UI. -->
 <!ENTITY debuggerUI.closeButton.tooltip "Close">
 
 <!-- LOCALIZATION NOTE (debuggerUI.panesButton.tooltip): This is the tooltip for
   -  the button that toggles the panes visible or hidden in the debugger UI. -->
 <!ENTITY debuggerUI.panesButton.tooltip "Toggle panes">
 
+<!-- LOCALIZATION NOTE (debuggerUI.blackBoxMessage.label): This is the message
+  - displayed to users when they select a black boxed source from the sources
+  - list in the debugger. -->
+<!ENTITY debuggerUI.blackBoxMessage.label "This source is black boxed: its breakpoints are disabled, and stepping skips through it.">
+
+<!-- LOCALIZATION NOTE (debuggerUI.blackBoxMessage.unBlackBoxButton): This is
+  - the text displayed in the button to stop black boxing the currently selected
+  - source. -->
+<!ENTITY debuggerUI.blackBoxMessage.unBlackBoxButton "Stop black boxing this source">
+
 <!-- LOCALIZATION NOTE (debuggerUI.optsButton.tooltip): This is the tooltip for
   -  the button that opens up an options context menu for the debugger UI. -->
 <!ENTITY debuggerUI.optsButton.tooltip  "Debugger Options">
 
 <!-- LOCALIZATION NOTE (debuggerUI.pauseExceptions): This is the label for the
   -  checkbox that toggles pausing on exceptions. -->
 <!ENTITY debuggerUI.pauseExceptions     "Pause on exceptions">
 <!ENTITY debuggerUI.pauseExceptions.key "E">
--- a/browser/metro/base/content/Util.js
+++ b/browser/metro/base/content/Util.js
@@ -222,18 +222,18 @@ let Util = {
             aElement.getAttributeNS(kXLinkNamespace, "type") == "simple");
   },
 
   isText: function isText(aElement) {
     return (aElement instanceof Ci.nsIDOMHTMLParagraphElement ||
             aElement instanceof Ci.nsIDOMHTMLDivElement ||
             aElement instanceof Ci.nsIDOMHTMLLIElement ||
             aElement instanceof Ci.nsIDOMHTMLPreElement ||
-            aElement instanceof HTMLHeadingElement ||
-            aElement instanceof HTMLTableCellElement ||
+            aElement instanceof Ci.nsIDOMHTMLHeadingElement ||
+            aElement instanceof Ci.nsIDOMHTMLTableCellElement ||
             aElement instanceof Ci.nsIDOMHTMLBodyElement);
   },
 
   /*
    * Rect and nsIDOMRect utilities
    */
 
   getCleanRect: function getCleanRect() {
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -1180,26 +1180,26 @@ var StartUI = {
       // of the keyboard transition.
       ContentAreaObserver.navBarWillBlur();
     }
 
     if (aEvent.button == 0)
       ContextUI.dismissTabs();
   },
 
-  onNarrowTitleClick: function onNarrowTitleClick(gridId) {
-    let grid = document.getElementById(gridId);
+  onNarrowTitleClick: function onNarrowTitleClick(sectionId) {
+    let section = document.getElementById(sectionId);
 
-    if (grid.hasAttribute("expanded"))
+    if (section.hasAttribute("expanded"))
       return;
 
-    for (let expandedGrid of Elements.startUI.querySelectorAll("[expanded]"))
-      expandedGrid.removeAttribute("expanded")
+    for (let expandedSection of Elements.startUI.querySelectorAll(".meta-section[expanded]"))
+      expandedSection.removeAttribute("expanded")
 
-    grid.setAttribute("expanded", "true");
+    section.setAttribute("expanded", "true");
   },
 
   handleEvent: function handleEvent(aEvent) {
     switch (aEvent.type) {
       case "contextmenu":
         let event = document.createEvent("Events");
         event.initEvent("MozEdgeUICompleted", true, false);
         window.dispatchEvent(event);
--- a/browser/metro/base/content/browser.xul
+++ b/browser/metro/base/content/browser.xul
@@ -192,41 +192,45 @@
           </vbox>
         </hbox>
 
         <!-- Start UI -->
         <hbox id="start-container" flex="1" observes="bcast_windowState" class="meta content-height content-width">
           <!-- portrait/landscape/filled view -->
 
           <scrollbox id="start-scrollbox" observes="bcast_preciseInput" flex="1">
-            <vbox id="start-topsites" class="meta-section">
+            <vbox id="start-topsites" class="meta-section" expanded="true">
               <label class="meta-section-title wide-title" value="&topSitesHeader.label;"/>
-              <label class="meta-section-title narrow-title" value="&snappedTopSitesHeader.label;"
-                onclick="StartUI.onNarrowTitleClick('start-topsites-grid')"/>
-              <richgrid id="start-topsites-grid" set-name="topSites" rows="3" columns="3" tiletype="thumbnail" seltype="multiple" flex="1" expanded="true"/>
+              <html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-topsites')">
+                &narrowTopSitesHeader.label;
+              </html:div>
+              <richgrid id="start-topsites-grid" set-name="topSites" rows="3" columns="3" tiletype="thumbnail" seltype="multiple" flex="1"/>
             </vbox>
 
             <vbox id="start-bookmarks" class="meta-section">
               <label class="meta-section-title wide-title" value="&bookmarksHeader.label;"/>
-              <label class="meta-section-title narrow-title" value="&snappedBookmarksHeader.label;"
-                onclick="StartUI.onNarrowTitleClick('start-bookmarks-grid')"/>
+              <html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-bookmarks')">
+                &narrowBookmarksHeader.label;
+              </html:div>
               <richgrid id="start-bookmarks-grid" set-name="bookmarks" seltype="multiple" flex="1"/>
             </vbox>
 
             <vbox id="start-history" class="meta-section">
               <label class="meta-section-title wide-title" value="&recentHistoryHeader.label;"/>
-              <label class="meta-section-title narrow-title" value="&snappedRecentHistoryHeader.label;"
-                onclick="StartUI.onNarrowTitleClick('start-history-grid')"/>
+              <html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-history')">
+                &narrowRecentHistoryHeader.label;
+              </html:div>
               <richgrid id="start-history-grid" set-name="recentHistory" seltype="multiple" flex="1"/>
             </vbox>
 
             <vbox id="start-remotetabs" class="meta-section">
               <label class="meta-section-title wide-title" value="&remoteTabsHeader.label;"/>
-              <label id="snappedRemoteTabsLabel" class="meta-section-title narrow-title" value="&snappedRemoteTabsHeader.label;"
-                onclick="StartUI.onNarrowTitleClick('start-remotetabs-grid')"/>
+              <html:div id="snappedRemoteTabsLabel" class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-remotetabs')">
+                &narrowRemoteTabsHeader.label;
+              </html:div>
               <richgrid id="start-remotetabs-grid" set-name="remoteTabs" seltype="multiple" flex="1"/>
             </vbox>
 
             <!-- Spacer to take extra space in snapped mode. -->
             <spacer flex="999"/>
           </scrollbox>
 
         </hbox>
--- a/browser/metro/base/content/contenthandlers/FormHelper.js
+++ b/browser/metro/base/content/contenthandlers/FormHelper.js
@@ -10,16 +10,17 @@ dump("### FormHelper.js loaded\n");
 
 let HTMLTextAreaElement = Ci.nsIDOMHTMLTextAreaElement;
 let HTMLInputElement = Ci.nsIDOMHTMLInputElement;
 let HTMLSelectElement = Ci.nsIDOMHTMLSelectElement;
 let HTMLIFrameElement = Ci.nsIDOMHTMLIFrameElement;
 let HTMLDocument = Ci.nsIDOMHTMLDocument;
 let HTMLHtmlElement = Ci.nsIDOMHTMLHtmlElement;
 let HTMLBodyElement = Ci.nsIDOMHTMLBodyElement;
+let HTMLLabelElement = Ci.nsIDOMHTMLLabelElement;
 let HTMLButtonElement = Ci.nsIDOMHTMLButtonElement;
 let HTMLOptGroupElement = Ci.nsIDOMHTMLOptGroupElement;
 let HTMLOptionElement = Ci.nsIDOMHTMLOptionElement;
 let XULMenuListElement = Ci.nsIDOMXULMenuListElement;
 
 /**
  * Responsible of navigation between forms fields and of the opening of the assistant
  */
--- a/browser/metro/locales/en-US/chrome/browser.dtd
+++ b/browser/metro/locales/en-US/chrome/browser.dtd
@@ -20,27 +20,27 @@
 <!ENTITY appbarFindInPage2.label    "Find in page">
 <!ENTITY appbarViewOnDesktop2.label "View on desktop">
 
 <!ENTITY topSitesHeader.label        "Top Sites">
 <!ENTITY bookmarksHeader.label       "Bookmarks">
 <!ENTITY recentHistoryHeader.label   "Recent History">
 <!ENTITY remoteTabsHeader.label      "Tabs from Other Devices">
 
-<!-- LOCALIZATION NOTE (snappedRemoteTabsHeader.label): shortened version of startRemoteTabsHeader.label.
-     Needs to be two words or shorter to fit in narrow vertical space.-->
-<!-- LOCALIZATION NOTE (snappedRemoteTabsHeader.label,
-                        snappedBookmarksHeader.label,
-                        snappedHistoryHeader.label,
-                        snappedTopSitesHeader.label )
-      The '>' character is not part of the name, but is an indicator of more content. Please do not localize the '>' -->
-<!ENTITY snappedRemoteTabsHeader.label    "Remote Tabs >">
-<!ENTITY snappedBookmarksHeader.label     "Bookmarks >">
-<!ENTITY snappedRecentHistoryHeader.label "Recent History >">
-<!ENTITY snappedTopSitesHeader.label      "Top Sites >">
+<!-- LOCALIZATION NOTE (narrowTopSitesHeader.label,
+                        narrowBookmarksHeader.label,
+                        narrowHistoryHeader.label,
+                        narrowRemoteTabsHeader.label )
+     are shortened versions of topSitesHeader.label, bookmarksHeader.label, recentHistoryHeader.label
+     and remoteTabsHeader.label. Need to be two words or shorter to fit in narrow vertical space.
+      -->
+<!ENTITY narrowTopSitesHeader.label      "Top Sites">
+<!ENTITY narrowBookmarksHeader.label     "Bookmarks">
+<!ENTITY narrowRecentHistoryHeader.label "Recent History">
+<!ENTITY narrowRemoteTabsHeader.label    "Remote Tabs">
 
 <!ENTITY downloadsHeader.label     "Downloads">
 <!ENTITY downloadShowPage.label    "Go to Page">
 <!ENTITY downloadShow2.label       "Find">
 <!ENTITY downloadOpen2.label       "Open">
 <!ENTITY downloadCancel.label      "Cancel">
 <!ENTITY downloadPause.label       "Pause">
 <!ENTITY downloadResume.label      "Resume">
--- a/browser/metro/theme/browser.css
+++ b/browser/metro/theme/browser.css
@@ -244,17 +244,17 @@ documenttab[selected] .documenttab-selec
   min-width: @grid_double_column_width@;
   -moz-box-flex: 1;
   -moz-box-align: center;
 }
 #start-container[viewstate="snapped"] richgrid {
   visibility: collapse;
 }
 
-#start-container[viewstate="snapped"] richgrid[expanded] {
+#start-container[viewstate="snapped"] .meta-section[expanded] > richgrid {
   visibility: visible;
 }
 
 /* Browser Content Areas ==================================================== */
 
 /* Hide the browser while the start UI is visible */
 #content-viewport[startpage],
 #content-viewport[filtering] {
--- a/browser/metro/theme/platform.css
+++ b/browser/metro/theme/platform.css
@@ -648,28 +648,41 @@ arrowbox {
   background-image: url("chrome://browser/skin/images/firefox-watermark.png");
   background-repeat: no-repeat;
   background-position: center center;
   padding: @metro_spacing_normal@ @metro_spacing_xxnormal@;
   overflow: auto;
   max-width: 100%;
   width: 100%;
 }
+
 .meta-section {
   margin: 0 @metro_spacing_large@;
 }
+
 .meta-section-title {
   font-size: @metro_font_large@;
   font-weight: 100;
   display: none;
+  cursor: default;
 }
+
 #start-container[viewstate="snapped"] .meta-section-title.narrow-title,
 #start-container:not([viewstate="snapped"]) .meta-section-title.wide-title {
   display: block;
 }
+
+.meta-section:not([expanded]) > .meta-section-title.narrow-title:-moz-locale-dir(ltr):after {
+  content: ">";
+}
+
+.meta-section:not([expanded]) > .meta-section-title.narrow-title:-moz-locale-dir(rtl):before {
+  content: "<";
+}
+
 /* App bars ----------------------------------------------------------------- */
 appbar {
   display: block;
   position: fixed;
   bottom: 0;
   width: 100%;
   transform: translateY(100%);
   transition: transform @metro_animation_duration@ @metro_animation_easing@;
--- a/browser/modules/webappsUI.jsm
+++ b/browser/modules/webappsUI.jsm
@@ -109,17 +109,17 @@ this.webappsUI = {
         let app = WebappsInstaller.install(aData);
         if (app) {
           let localDir = null;
           if (app.appProfile) {
             localDir = app.appProfile.localDir;
           }
 
           DOMApplicationRegistry.confirmInstall(aData, false, localDir);
-          installationSuccessNotification(app, aWindow);
+          installationSuccessNotification(aData, app, aWindow);
         } else {
           DOMApplicationRegistry.denyInstall(aData);
         }
       }
     };
 
     let requestingURI = aWindow.makeURI(aData.from);
     let manifest = new ManifestHelper(aData.app.manifest, aData.app.origin);
@@ -135,25 +135,33 @@ this.webappsUI = {
                                             [manifest.name, host], 2);
 
     aWindow.PopupNotifications.show(aBrowser, "webapps-install", message,
                                     "webapps-notification-icon", mainAction);
 
   }
 }
 
-function installationSuccessNotification(app, aWindow) {
+function installationSuccessNotification(aData, app, aWindow) {
+  let launcher = {
+    observe: function(aSubject, aTopic) {
+      if (aTopic == "alertclickcallback") {
+        WebappOSUtils.launch(aData.app);
+      }
+    }
+  };
+
   let bundle = aWindow.gNavigatorBundle;
 
   if (("@mozilla.org/alerts-service;1" in Cc)) {
     let notifier;
     try {
       notifier = Cc["@mozilla.org/alerts-service;1"].
                  getService(Ci.nsIAlertsService);
 
       notifier.showAlertNotification(app.iconURI.spec,
                                     bundle.getString("webapps.install.success"),
                                     app.appNameAsFilename,
-                                    false, null, null);
+                                    true, null, launcher);
 
     } catch (ex) {}
   }
 }
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dbd7a3e5ec9fab846ea8d0010b947c7874eb9887
GIT binary patch
literal 836
zc$@)51H1f*P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00006VoOIv0RI60
z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3J~PEgVb|fR6wG0?|oC
zK~zY`?Nm)jR8bWE?!EIz&JPwe<KUP@rjZ#%WMU*_6cL!T32IY>xQifYAq1_8b}bCi
zNGX*3Nox=cq!vjahKn)>9gS!loq12kY2LgU=Z!P(z7{=UQ0!+H<OgSU&-u>z&i(EM
zwy=eN9^_YtAAK{90@u!qAf${@wvP}vDW!ySzMNH6pT>DGEQmda%gdJjsw=a*X=riz
zawH~?E=wzu3u5%;<7YjmnB85->~2r%)91DG!t$#~EIApKk`wbnq=DJp^p6xUyPGY1
z^*vxlQ!UT(w46)?k5<(*$#Oyhkk)HVHk;KkKKkxnUY@nkz^G+4t-L5IIe1@<hj=a@
zT|aqn_VZn8Fji+Ws-zKQyL<aPWH}KX8yWV90e{O<aHeH!WY{CiiD-9ke+MB@Gg(zK
znay<p|EC-4m5^NWxtWPuCX1ymljSJ@n#NVNXzzjR0HpA@=?)Fl`Ll?N1;u68066Bp
z_?{5T7yx22FsqVU>E2a(sCi9^A*Y!!kxW`0CUXKn7Jx<w)c_~}NGg?9%ofWE04PdY
z(T7tAp&31&sGReZqHNcBS2wJvs^)C_qPRFi3E==T21cp3ud4(A2E2ovk`xO`QcM`|
z4t4^7x38<jz$gWfp@eWDEKDCid8R#gGr22b0IV*jvtY>E+vs$;JkY?Qsqxx#7j91b
zXDt96db(6rTB5vt?R^Ns>>!{*I2<@%f2mCnMFBuUjfd0?F4CLWTu!I6qwP_BMMe1$
z#+XUd)JQNm-+JuC=_vsC@czwykEgJa5VnJJo}HTVPh7d$&?ktZ2tZyV-_)i6@&M#l
zS5+3=X}VpxXLqs3VY7LRMwSl%s><WvrFbAP7hGs=X&d(r4$T3G0!ZePZ~BsTtC<08
z)58cr1Hg0aP4vrM(IdT{{I_3)uEwAT%gJABmIaUjz}0w2+xmI`Q~Ur{l0<#CcZdG~
O0000<MNUMnLSTY9kaFz+
--- a/browser/themes/linux/devtools/debugger.css
+++ b/browser/themes/linux/devtools/debugger.css
@@ -49,16 +49,35 @@
 .side-menu-widget-item-checkbox[checked] > .checkbox-check {
   background-position: 0 0;
 }
 
 .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents > .dbg-breakpoint {
   display: none;
 }
 
+/* Black box message */
+
+#black-boxed-message {
+  padding: 100px 50px;
+  background-color: rgb(61, 69, 76);
+  color: white;
+}
+
+#black-boxed-message-label,
+#black-boxed-message-button {
+  text-align: center;
+  font-size: 150%;
+}
+
+#black-boxed-message-button {
+  margin-top: 1em;
+  padding: .25em;
+}
+
 /* ListWidget items */
 
 .list-widget-item {
   padding: 2px;
 }
 
 .list-widget-item:not(.selected):not(.empty):hover {
   background: linear-gradient(rgba(255,255,255,0.9), rgba(255,255,255,0.85)), Highlight;
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -173,16 +173,17 @@ browser.jar:
   skin/classic/browser/devtools/styleeditor.css       (devtools/styleeditor.css)
   skin/classic/browser/devtools/debugger.css          (devtools/debugger.css)
 * skin/classic/browser/devtools/profiler.css          (devtools/profiler.css)
   skin/classic/browser/devtools/netmonitor.css        (devtools/netmonitor.css)
 * skin/classic/browser/devtools/scratchpad.css        (devtools/scratchpad.css)
   skin/classic/browser/devtools/magnifying-glass.png  (devtools/magnifying-glass.png)
   skin/classic/browser/devtools/option-icon.png       (devtools/option-icon.png)
   skin/classic/browser/devtools/itemToggle.png        (devtools/itemToggle.png)
+  skin/classic/browser/devtools/blackBoxMessageEye.png (devtools/blackBoxMessageEye.png)
   skin/classic/browser/devtools/itemArrow-rtl.png     (devtools/itemArrow-rtl.png)
   skin/classic/browser/devtools/itemArrow-ltr.png     (devtools/itemArrow-ltr.png)
   skin/classic/browser/devtools/background-noise-toolbar.png (devtools/background-noise-toolbar.png)
   skin/classic/browser/devtools/inspect-button.png    (devtools/inspect-button.png)
   skin/classic/browser/devtools/dropmarker.png        (devtools/dropmarker.png)
   skin/classic/browser/devtools/layout-background-grid.png (devtools/layout-background-grid.png)
   skin/classic/browser/devtools/layoutview.css        (devtools/layoutview.css)
   skin/classic/browser/devtools/debugger-collapse.png  (devtools/debugger-collapse.png)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dbd7a3e5ec9fab846ea8d0010b947c7874eb9887
GIT binary patch
literal 836
zc$@)51H1f*P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00006VoOIv0RI60
z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3J~PEgVb|fR6wG0?|oC
zK~zY`?Nm)jR8bWE?!EIz&JPwe<KUP@rjZ#%WMU*_6cL!T32IY>xQifYAq1_8b}bCi
zNGX*3Nox=cq!vjahKn)>9gS!loq12kY2LgU=Z!P(z7{=UQ0!+H<OgSU&-u>z&i(EM
zwy=eN9^_YtAAK{90@u!qAf${@wvP}vDW!ySzMNH6pT>DGEQmda%gdJjsw=a*X=riz
zawH~?E=wzu3u5%;<7YjmnB85->~2r%)91DG!t$#~EIApKk`wbnq=DJp^p6xUyPGY1
z^*vxlQ!UT(w46)?k5<(*$#Oyhkk)HVHk;KkKKkxnUY@nkz^G+4t-L5IIe1@<hj=a@
zT|aqn_VZn8Fji+Ws-zKQyL<aPWH}KX8yWV90e{O<aHeH!WY{CiiD-9ke+MB@Gg(zK
znay<p|EC-4m5^NWxtWPuCX1ymljSJ@n#NVNXzzjR0HpA@=?)Fl`Ll?N1;u68066Bp
z_?{5T7yx22FsqVU>E2a(sCi9^A*Y!!kxW`0CUXKn7Jx<w)c_~}NGg?9%ofWE04PdY
z(T7tAp&31&sGReZqHNcBS2wJvs^)C_qPRFi3E==T21cp3ud4(A2E2ovk`xO`QcM`|
z4t4^7x38<jz$gWfp@eWDEKDCid8R#gGr22b0IV*jvtY>E+vs$;JkY?Qsqxx#7j91b
zXDt96db(6rTB5vt?R^Ns>>!{*I2<@%f2mCnMFBuUjfd0?F4CLWTu!I6qwP_BMMe1$
z#+XUd)JQNm-+JuC=_vsC@czwykEgJa5VnJJo}HTVPh7d$&?ktZ2tZyV-_)i6@&M#l
zS5+3=X}VpxXLqs3VY7LRMwSl%s><WvrFbAP7hGs=X&d(r4$T3G0!ZePZ~BsTtC<08
z)58cr1Hg0aP4vrM(IdT{{I_3)uEwAT%gJABmIaUjz}0w2+xmI`Q~Ur{l0<#CcZdG~
O0000<MNUMnLSTY9kaFz+
--- a/browser/themes/osx/devtools/debugger.css
+++ b/browser/themes/osx/devtools/debugger.css
@@ -51,16 +51,35 @@
 .side-menu-widget-item-checkbox[checked] > .checkbox-check {
   background-position: 0 0;
 }
 
 .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents > .dbg-breakpoint {
   display: none;
 }
 
+/* Black box message */
+
+#black-boxed-message {
+  padding: 100px 50px;
+  background-color: rgb(61, 69, 76);
+  color: white;
+}
+
+#black-boxed-message-label,
+#black-boxed-message-button {
+  text-align: center;
+  font-size: 150%;
+}
+
+#black-boxed-message-button {
+  margin-top: 1em;
+  padding: .25em;
+}
+
 /* ListWidget items */
 
 .list-widget-item {
   padding: 2px;
 }
 
 .list-widget-item:not(.selected):not(.empty):hover {
   background: linear-gradient(rgba(255,255,255,0.9), rgba(255,255,255,0.85)), Highlight;
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -264,16 +264,17 @@ browser.jar:
   skin/classic/browser/devtools/styleeditor.css             (devtools/styleeditor.css)
 * skin/classic/browser/devtools/debugger.css                (devtools/debugger.css)
 * skin/classic/browser/devtools/profiler.css                (devtools/profiler.css)
   skin/classic/browser/devtools/netmonitor.css              (devtools/netmonitor.css)
 * skin/classic/browser/devtools/scratchpad.css              (devtools/scratchpad.css)
   skin/classic/browser/devtools/magnifying-glass.png        (devtools/magnifying-glass.png)
   skin/classic/browser/devtools/option-icon.png             (devtools/option-icon.png)
   skin/classic/browser/devtools/itemToggle.png              (devtools/itemToggle.png)
+  skin/classic/browser/devtools/blackBoxMessageEye.png      (devtools/blackBoxMessageEye.png)
   skin/classic/browser/devtools/itemArrow-rtl.png           (devtools/itemArrow-rtl.png)
   skin/classic/browser/devtools/itemArrow-ltr.png           (devtools/itemArrow-ltr.png)
   skin/classic/browser/devtools/background-noise-toolbar.png (devtools/background-noise-toolbar.png)
   skin/classic/browser/devtools/inspect-button.png          (devtools/inspect-button.png)
   skin/classic/browser/devtools/dropmarker.png              (devtools/dropmarker.png)
   skin/classic/browser/devtools/layout-background-grid.png  (devtools/layout-background-grid.png)
   skin/classic/browser/devtools/layoutview.css              (devtools/layoutview.css)
   skin/classic/browser/devtools/debugger-collapse.png       (devtools/debugger-collapse.png)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dbd7a3e5ec9fab846ea8d0010b947c7874eb9887
GIT binary patch
literal 836
zc$@)51H1f*P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00006VoOIv0RI60
z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3J~PEgVb|fR6wG0?|oC
zK~zY`?Nm)jR8bWE?!EIz&JPwe<KUP@rjZ#%WMU*_6cL!T32IY>xQifYAq1_8b}bCi
zNGX*3Nox=cq!vjahKn)>9gS!loq12kY2LgU=Z!P(z7{=UQ0!+H<OgSU&-u>z&i(EM
zwy=eN9^_YtAAK{90@u!qAf${@wvP}vDW!ySzMNH6pT>DGEQmda%gdJjsw=a*X=riz
zawH~?E=wzu3u5%;<7YjmnB85->~2r%)91DG!t$#~EIApKk`wbnq=DJp^p6xUyPGY1
z^*vxlQ!UT(w46)?k5<(*$#Oyhkk)HVHk;KkKKkxnUY@nkz^G+4t-L5IIe1@<hj=a@
zT|aqn_VZn8Fji+Ws-zKQyL<aPWH}KX8yWV90e{O<aHeH!WY{CiiD-9ke+MB@Gg(zK
znay<p|EC-4m5^NWxtWPuCX1ymljSJ@n#NVNXzzjR0HpA@=?)Fl`Ll?N1;u68066Bp
z_?{5T7yx22FsqVU>E2a(sCi9^A*Y!!kxW`0CUXKn7Jx<w)c_~}NGg?9%ofWE04PdY
z(T7tAp&31&sGReZqHNcBS2wJvs^)C_qPRFi3E==T21cp3ud4(A2E2ovk`xO`QcM`|
z4t4^7x38<jz$gWfp@eWDEKDCid8R#gGr22b0IV*jvtY>E+vs$;JkY?Qsqxx#7j91b
zXDt96db(6rTB5vt?R^Ns>>!{*I2<@%f2mCnMFBuUjfd0?F4CLWTu!I6qwP_BMMe1$
z#+XUd)JQNm-+JuC=_vsC@czwykEgJa5VnJJo}HTVPh7d$&?ktZ2tZyV-_)i6@&M#l
zS5+3=X}VpxXLqs3VY7LRMwSl%s><WvrFbAP7hGs=X&d(r4$T3G0!ZePZ~BsTtC<08
z)58cr1Hg0aP4vrM(IdT{{I_3)uEwAT%gJABmIaUjz}0w2+xmI`Q~Ur{l0<#CcZdG~
O0000<MNUMnLSTY9kaFz+
--- a/browser/themes/windows/devtools/debugger.css
+++ b/browser/themes/windows/devtools/debugger.css
@@ -49,16 +49,35 @@
 .side-menu-widget-item-checkbox[checked] > .checkbox-check {
   background-position: 0 0;
 }
 
 .side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents > .dbg-breakpoint {
   display: none;
 }
 
+/* Black box message */
+
+#black-boxed-message {
+  padding: 100px 50px;
+  background-color: rgb(61, 69, 76);
+  color: white;
+}
+
+#black-boxed-message-label,
+#black-boxed-message-button {
+  text-align: center;
+  font-size: 150%;
+}
+
+#black-boxed-message-button {
+  margin-top: 1em;
+  padding: .25em;
+}
+
 /* ListWidget items */
 
 .list-widget-item {
   padding: 2px;
 }
 
 .list-widget-item:not(.selected):not(.empty):hover {
   background: linear-gradient(rgba(255,255,255,0.9), rgba(255,255,255,0.85)), Highlight;
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -200,16 +200,17 @@ browser.jar:
         skin/classic/browser/devtools/styleeditor.css               (devtools/styleeditor.css)
         skin/classic/browser/devtools/debugger.css                  (devtools/debugger.css)
 *       skin/classic/browser/devtools/profiler.css                  (devtools/profiler.css)
         skin/classic/browser/devtools/netmonitor.css                (devtools/netmonitor.css)
 *       skin/classic/browser/devtools/scratchpad.css                (devtools/scratchpad.css)
         skin/classic/browser/devtools/magnifying-glass.png          (devtools/magnifying-glass.png)
         skin/classic/browser/devtools/option-icon.png               (devtools/option-icon.png)
         skin/classic/browser/devtools/itemToggle.png                (devtools/itemToggle.png)
+        skin/classic/browser/devtools/blackBoxMessageEye.png        (devtools/blackBoxMessageEye.png)
         skin/classic/browser/devtools/itemArrow-rtl.png             (devtools/itemArrow-rtl.png)
         skin/classic/browser/devtools/itemArrow-ltr.png             (devtools/itemArrow-ltr.png)
         skin/classic/browser/devtools/background-noise-toolbar.png  (devtools/background-noise-toolbar.png)
         skin/classic/browser/devtools/inspect-button.png            (devtools/inspect-button.png)
         skin/classic/browser/devtools/dropmarker.png                (devtools/dropmarker.png)
         skin/classic/browser/devtools/layout-background-grid.png    (devtools/layout-background-grid.png)
         skin/classic/browser/devtools/layoutview.css                (devtools/layoutview.css)
         skin/classic/browser/devtools/debugger-collapse.png         (devtools/debugger-collapse.png)
@@ -455,16 +456,17 @@ browser.jar:
         skin/classic/aero/browser/devtools/styleeditor.css           (devtools/styleeditor.css)
         skin/classic/aero/browser/devtools/debugger.css              (devtools/debugger.css)
 *       skin/classic/aero/browser/devtools/profiler.css              (devtools/profiler.css)
         skin/classic/aero/browser/devtools/netmonitor.css            (devtools/netmonitor.css)
 *       skin/classic/aero/browser/devtools/scratchpad.css            (devtools/scratchpad.css)
         skin/classic/aero/browser/devtools/magnifying-glass.png      (devtools/magnifying-glass.png)
         skin/classic/aero/browser/devtools/option-icon.png           (devtools/option-icon.png)
         skin/classic/aero/browser/devtools/itemToggle.png            (devtools/itemToggle.png)
+        skin/classic/aero/browser/devtools/blackBoxMessageEye.png    (devtools/blackBoxMessageEye.png)
         skin/classic/aero/browser/devtools/itemArrow-rtl.png         (devtools/itemArrow-rtl.png)
         skin/classic/aero/browser/devtools/background-noise-toolbar.png (devtools/background-noise-toolbar.png)
         skin/classic/aero/browser/devtools/itemArrow-ltr.png         (devtools/itemArrow-ltr.png)
         skin/classic/aero/browser/devtools/inspect-button.png        (devtools/inspect-button.png)
         skin/classic/aero/browser/devtools/dropmarker.png            (devtools/dropmarker.png)
         skin/classic/aero/browser/devtools/layout-background-grid.png (devtools/layout-background-grid.png)
         skin/classic/aero/browser/devtools/layoutview.css            (devtools/layoutview.css)
         skin/classic/aero/browser/devtools/debugger-collapse.png     (devtools/debugger-collapse.png)
--- a/build/autoconf/libstdcxx.py
+++ b/build/autoconf/libstdcxx.py
@@ -56,16 +56,18 @@ def encode_ver(v):
 def find_version(e):
     """Given the value of environment variable CXX or HOST_CXX, find the
     version of the libstdc++ it uses.
     """
     args = e.split()
     args +=  ['-shared', '-Wl,-t']
     p = subprocess.Popen(args, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
     candidates = [x for x in p.stdout if 'libstdc++.so' in x]
+    if not candidates:
+        return ''
     assert len(candidates) == 1
     libstdcxx = parse_ld_line(candidates[-1])
 
     p = subprocess.Popen(['readelf', '-V', libstdcxx], stdout=subprocess.PIPE)
     versions = [parse_readelf_line(x)
                 for x in p.stdout.readlines() if 'Name: GLIBCXX' in x]
     last_version = sorted(versions, cmp = cmp_ver)[-1]
     return encode_ver(last_version)
--- a/build/unix/moz.build
+++ b/build/unix/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-if CONFIG['STDCXX_COMPAT']:
+if CONFIG['MOZ_LIBSTDCXX_TARGET_VERSION'] or CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']:
     DIRS += ['stdc++compat']
 
 if CONFIG['USE_ELF_HACK']:
     DIRS += ['elfhack']
 
 TEST_DIRS += ['test']
 
 MODULE = 'build'
--- a/build/unix/stdc++compat/Makefile.in
+++ b/build/unix/stdc++compat/Makefile.in
@@ -9,16 +9,16 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 FORCE_STATIC_LIB= 1
 STL_FLAGS =
 NO_EXPAND_LIBS = 1
 NO_PROFILE_GUIDED_OPTIMIZE = 1
 
-  $(NULL)
-
-HOST_CPPSRCS = $(CPPSRCS)
+ifdef MOZ_LIBSTDCXX_HOST_VERSION
+HOST_CPPSRCS = stdc++compat.cpp
+endif
 
 include $(topsrcdir)/config/rules.mk
 
 CXXFLAGS += -DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_TARGET_VERSION)
-HOST_CXXFLAGS += -DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_TARGET_VERSION)
+HOST_CXXFLAGS += -DMOZ_LIBSTDCXX_VERSION=$(MOZ_LIBSTDCXX_HOST_VERSION)
--- a/build/unix/stdc++compat/moz.build
+++ b/build/unix/stdc++compat/moz.build
@@ -1,16 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 MODULE = 'build'
 
-CPP_SOURCES += [
-    'stdc++compat.cpp',
-]
+if CONFIG['MOZ_LIBSTDCXX_TARGET_VERSION']:
+    LIBRARY_NAME = 'stdc++compat'
+    CPP_SOURCES += ['stdc++compat.cpp']
 
-HOST_LIBRARY_NAME = 'host_stdc++compat'
+if CONFIG['MOZ_LIBSTDCXX_HOST_VERSION']:
+    HOST_LIBRARY_NAME = 'host_stdc++compat'
 
-LIBRARY_NAME = 'stdc++compat'
-
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -12,17 +12,17 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 # For sanity's sake, we compile nsinstall without the wrapped system
 # headers, so that we can use it to set up the wrapped system headers.
 VISIBILITY_FLAGS =
 
 # STDCXX_COMPAT is not needed here, and will actually fail because
 # libstdc++-compat is not built yet.
-STDCXX_COMPAT =
+MOZ_LIBSTDCXX_HOST_VERSION =
 
 ifneq (WINNT,$(HOST_OS_ARCH))
 HOST_PROGRAM	= nsinstall_real$(HOST_BIN_SUFFIX)
 endif
 
 ifndef CROSS_COMPILE
 ifdef USE_ELF_DYNSTR_GC
 export:: elf-dynstr-gc
--- a/config/config.mk
+++ b/config/config.mk
@@ -742,24 +742,28 @@ EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselis
 EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
 EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist -- $(LD)
 EXPAND_MKSHLIB_ARGS = --uselist
 ifdef SYMBOL_ORDER
 EXPAND_MKSHLIB_ARGS += --symbol-order $(SYMBOL_ORDER)
 endif
 EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) $(EXPAND_MKSHLIB_ARGS) -- $(MKSHLIB)
 
-ifdef STDCXX_COMPAT
+ifneq (,$(MOZ_LIBSTDCXX_TARGET_VERSION)$(MOZ_LIBSTDCXX_HOST_VERSION))
 ifneq ($(OS_ARCH),Darwin)
 CHECK_STDCXX = objdump -p $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' > /dev/null && echo "TEST-UNEXPECTED-FAIL | | We don't want these libstdc++ symbols to be used:" && objdump -T $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && exit 1 || exit 0
 endif
 
+ifdef MOZ_LIBSTDCXX_TARGET_VERSION
 EXTRA_LIBS += $(call EXPAND_LIBNAME_PATH,stdc++compat,$(DEPTH)/build/unix/stdc++compat)
+endif
+ifdef MOZ_LIBSTDCXX_HOST_VERSION
 HOST_EXTRA_LIBS += $(call EXPAND_LIBNAME_PATH,host_stdc++compat,$(DEPTH)/build/unix/stdc++compat)
 endif
+endif
 
 # autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
 # this file
 OBJ_SUFFIX := $(_OBJ_SUFFIX)
 
 # PGO builds with GCC build objects with instrumentation in a first pass,
 # then objects optimized, without instrumentation, in a second pass. If
 # we overwrite the ojects from the first pass with those from the second,
--- a/configure.in
+++ b/configure.in
@@ -7529,20 +7529,18 @@ dnl ====================================
 dnl = libstdc++ compatibility hacks
 dnl ========================================================
 
 STDCXX_COMPAT=
 MOZ_ARG_ENABLE_BOOL(stdcxx-compat,
 [  --enable-stdcxx-compat  Enable compatibility with older libstdc++],
     STDCXX_COMPAT=1)
 
-AC_SUBST(STDCXX_COMPAT)
-
 if test -n "$STDCXX_COMPAT"; then
-   eval $(CXX="$CXX" $PYTHON $_topsrcdir/build/autoconf/libstdcxx.py)
+   eval $(CXX="$CXX" HOST_CXX="$HOST_CXX" $PYTHON $_topsrcdir/build/autoconf/libstdcxx.py)
    AC_SUBST(MOZ_LIBSTDCXX_TARGET_VERSION)
    AC_SUBST(MOZ_LIBSTDCXX_HOST_VERSION)
 fi
 
 dnl ========================================================
 dnl =
 dnl = Profiling and Instrumenting
 dnl =
--- a/content/html/content/src/HTMLDataListElement.cpp
+++ b/content/html/content/src/HTMLDataListElement.cpp
@@ -22,25 +22,36 @@ HTMLDataListElement::WrapNode(JSContext 
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED_1(HTMLDataListElement, nsGenericHTMLElement,
                                      mOptions)
 
 NS_IMPL_ADDREF_INHERITED(HTMLDataListElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLDataListElement, Element)
 
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLDataListElement)
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLDataListElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLDataListElement,
+                                nsIDOMHTMLDataListElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLDataListElement)
 
 bool
 HTMLDataListElement::MatchOptions(nsIContent* aContent, int32_t aNamespaceID,
                                   nsIAtom* aAtom, void* aData)
 {
   return aContent->NodeInfo()->Equals(nsGkAtoms::option, kNameSpaceID_XHTML) &&
          !aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
 }
 
+NS_IMETHODIMP
+HTMLDataListElement::GetOptions(nsIDOMHTMLCollection** aOptions)
+{
+  NS_ADDREF(*aOptions = Options());
+
+  return NS_OK;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/src/HTMLDataListElement.h
+++ b/content/html/content/src/HTMLDataListElement.h
@@ -2,23 +2,24 @@
 /* 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 HTMLDataListElement_h___
 #define HTMLDataListElement_h___
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLDataListElement.h"
 #include "nsContentList.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLDataListElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLElement
+                                      public nsIDOMHTMLDataListElement
 {
 public:
   HTMLDataListElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLDataListElement();
 
@@ -29,16 +30,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLDataListElement
+  NS_DECL_NSIDOMHTMLDATALISTELEMENT
+
   nsContentList* Options()
   {
     if (!mOptions) {
       mOptions = new nsContentList(this, MatchOptions, nullptr, nullptr, true);
     }
 
     return mOptions;
   }
--- a/content/html/content/src/HTMLFontElement.cpp
+++ b/content/html/content/src/HTMLFontElement.cpp
@@ -26,23 +26,76 @@ HTMLFontElement::WrapNode(JSContext *aCx
 {
   return HTMLFontElementBinding::Wrap(aCx, aScope, this);
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLFontElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLFontElement, Element)
 
 // QueryInterface implementation for HTMLFontElement
-NS_INTERFACE_MAP_BEGIN(HTMLFontElement)
+NS_INTERFACE_TABLE_HEAD(HTMLFontElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLFontElement, nsIDOMHTMLFontElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLFontElement)
 
+NS_IMETHODIMP
+HTMLFontElement::GetColor(nsAString& aColor)
+{
+  nsString color;
+  GetColor(color);
+  aColor = color;
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+HTMLFontElement::SetColor(const nsAString& aColor)
+{
+  ErrorResult rv;
+  SetColor(aColor, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLFontElement::GetFace(nsAString& aFace)
+{
+  nsString face;
+  GetFace(face);
+  aFace = face;
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+HTMLFontElement::SetFace(const nsAString& aFace)
+{
+  ErrorResult rv;
+  SetFace(aFace, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLFontElement::GetSize(nsAString& aSize)
+{
+  nsString size;
+  GetSize(size);
+  aSize = size;
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+HTMLFontElement::SetSize(const nsAString& aSize)
+{
+  ErrorResult rv;
+  SetSize(aSize, rv);
+  return rv.ErrorCode();
+}
+
 bool
 HTMLFontElement::ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::size) {
--- a/content/html/content/src/HTMLFontElement.h
+++ b/content/html/content/src/HTMLFontElement.h
@@ -2,22 +2,23 @@
 /* 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 HTMLFontElement_h___
 #define HTMLFontElement_h___
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLFontElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLFontElement MOZ_FINAL : public nsGenericHTMLElement,
-                                  public nsIDOMHTMLElement
+                                  public nsIDOMHTMLFontElement
 {
 public:
   HTMLFontElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLFontElement();
 
@@ -28,16 +29,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLFontElement
+  NS_DECL_NSIDOMHTMLFONTELEMENT
+
   void GetColor(nsString& aColor)
   {
     GetHTMLAttr(nsGkAtoms::color, aColor);
   }
   void SetColor(const nsAString& aColor, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::color, aColor, aError);
   }
--- a/content/html/content/src/HTMLHeadingElement.cpp
+++ b/content/html/content/src/HTMLHeadingElement.cpp
@@ -21,29 +21,35 @@ namespace dom {
 HTMLHeadingElement::~HTMLHeadingElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLHeadingElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLHeadingElement, Element)
 
 // QueryInterface implementation for HTMLHeadingElement
-NS_INTERFACE_MAP_BEGIN(HTMLHeadingElement)
+NS_INTERFACE_TABLE_HEAD(HTMLHeadingElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLHeadingElement,
+                                nsIDOMHTMLHeadingElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLHeadingElement)
 
 JSObject*
 HTMLHeadingElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLHeadingElementBinding::Wrap(aCx, aScope, this);
 }
 
+NS_IMPL_STRING_ATTR(HTMLHeadingElement, Align, align)
+
+
 bool
 HTMLHeadingElement::ParseAttribute(int32_t aNamespaceID,
                                    nsIAtom* aAttribute,
                                    const nsAString& aValue,
                                    nsAttrValue& aResult)
 {
   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
     return ParseDivAlignValue(aValue, aResult);
--- a/content/html/content/src/HTMLHeadingElement.h
+++ b/content/html/content/src/HTMLHeadingElement.h
@@ -2,23 +2,24 @@
 /* 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 mozilla_dom_HTMLHeadingElement_h
 #define mozilla_dom_HTMLHeadingElement_h
 
 #include "mozilla/Attributes.h"
+#include "nsIDOMHTMLHeadingElement.h"
 #include "nsGenericHTMLElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLHeadingElement MOZ_FINAL : public nsGenericHTMLElement,
-                                     public nsIDOMHTMLElement
+				     public nsIDOMHTMLHeadingElement
 {
 public:
   HTMLHeadingElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLHeadingElement();
 
@@ -29,34 +30,30 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLHeadingElement
+  NS_DECL_NSIDOMHTMLHEADINGELEMENT
+
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
   nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
-  void GetAlign(nsAString& aAlign)
-  {
-    GetHTMLAttr(nsGkAtoms::align, aAlign);
-  }
-  void SetAlign(const nsAString& aAlign, ErrorResult& aRv)
-  {
-    SetHTMLAttr(nsGkAtoms::align, aAlign, aRv);
-  }
-
+  // The XPCOM versions of GetAlign and SetAlign are fine for us for
+  // use from WebIDL.
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 };
 
 } // namespace mozilla
 } // namespace dom
--- a/content/html/content/src/HTMLLabelElement.cpp
+++ b/content/html/content/src/HTMLLabelElement.cpp
@@ -30,23 +30,59 @@ HTMLLabelElement::WrapNode(JSContext *aC
 
 // nsISupports
 
 
 NS_IMPL_ADDREF_INHERITED(HTMLLabelElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLLabelElement, Element)
 
 // QueryInterface implementation for HTMLLabelElement
-NS_INTERFACE_MAP_BEGIN(HTMLLabelElement)
+NS_INTERFACE_TABLE_HEAD(HTMLLabelElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLLabelElement,
+                                nsIDOMHTMLLabelElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
+// nsIDOMHTMLLabelElement
+
 NS_IMPL_ELEMENT_CLONE(HTMLLabelElement)
 
+NS_IMETHODIMP
+HTMLLabelElement::GetForm(nsIDOMHTMLFormElement** aForm)
+{
+  return nsGenericHTMLFormElement::GetForm(aForm);
+}
+
+NS_IMETHODIMP
+HTMLLabelElement::GetControl(nsIDOMHTMLElement** aElement)
+{
+  nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(GetLabeledElement());
+  element.forget(aElement);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLLabelElement::SetHtmlFor(const nsAString& aHtmlFor)
+{
+  ErrorResult rv;
+  SetHtmlFor(aHtmlFor, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLLabelElement::GetHtmlFor(nsAString& aHtmlFor)
+{
+  nsString htmlFor;
+  GetHtmlFor(htmlFor);
+  aHtmlFor = htmlFor;
+  return NS_OK;
+}
+
 void
 HTMLLabelElement::Focus(ErrorResult& aError)
 {
   // retarget the focus method at the for content
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   if (fm) {
     nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(GetLabeledElement());
     if (elem)
--- a/content/html/content/src/HTMLLabelElement.h
+++ b/content/html/content/src/HTMLLabelElement.h
@@ -6,22 +6,23 @@
 /**
  * Declaration of HTML <label> elements.
  */
 #ifndef HTMLLabelElement_h
 #define HTMLLabelElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLLabelElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLLabelElement MOZ_FINAL : public nsGenericHTMLFormElement,
-                                   public nsIDOMHTMLElement
+                                   public nsIDOMHTMLLabelElement
 {
 public:
   HTMLLabelElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLFormElement(aNodeInfo),
       mHandlingEvent(false)
   {
   }
   virtual ~HTMLLabelElement();
@@ -32,16 +33,19 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLLabelElement
+  NS_DECL_NSIDOMHTMLLABELELEMENT
+
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
   using nsGenericHTMLFormElement::GetForm;
   void GetHtmlFor(nsString& aHtmlFor)
   {
     GetHTMLAttr(nsGkAtoms::_for, aHtmlFor);
   }
--- a/content/html/content/src/HTMLLegendElement.cpp
+++ b/content/html/content/src/HTMLLegendElement.cpp
@@ -20,23 +20,40 @@ HTMLLegendElement::~HTMLLegendElement()
 }
 
 
 NS_IMPL_ADDREF_INHERITED(HTMLLegendElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLLegendElement, Element)
 
 
 // QueryInterface implementation for HTMLLegendElement
-NS_INTERFACE_MAP_BEGIN(HTMLLegendElement)
+NS_INTERFACE_TABLE_HEAD(HTMLLegendElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLLegendElement, nsIDOMHTMLLegendElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
+// nsIDOMHTMLLegendElement
+
+
 NS_IMPL_ELEMENT_CLONE(HTMLLegendElement)
 
+
+NS_IMETHODIMP
+HTMLLegendElement::GetForm(nsIDOMHTMLFormElement** aForm)
+{
+  Element* form = GetFormElement();
+
+  return form ? CallQueryInterface(form, aForm) : NS_OK;
+}
+
+
+NS_IMPL_STRING_ATTR(HTMLLegendElement, Align, align)
+
 // this contains center, because IE4 does
 static const nsAttrValue::EnumTable kAlignTable[] = {
   { "left", NS_STYLE_TEXT_ALIGN_LEFT },
   { "right", NS_STYLE_TEXT_ALIGN_RIGHT },
   { "center", NS_STYLE_TEXT_ALIGN_CENTER },
   { "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
   { "top", NS_STYLE_VERTICAL_ALIGN_TOP },
   { 0 }
--- a/content/html/content/src/HTMLLegendElement.h
+++ b/content/html/content/src/HTMLLegendElement.h
@@ -2,24 +2,25 @@
 /* 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 mozilla_dom_HTMLLegendElement_h
 #define mozilla_dom_HTMLLegendElement_h
 
 #include "mozilla/Attributes.h"
+#include "nsIDOMHTMLLegendElement.h"
 #include "nsGenericHTMLElement.h"
 #include "mozilla/dom/HTMLFormElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLLegendElement MOZ_FINAL : public nsGenericHTMLElement,
-                                    public nsIDOMHTMLElement
+                                    public nsIDOMHTMLLegendElement
 {
 public:
   HTMLLegendElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLLegendElement();
 
@@ -29,16 +30,19 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLLegendElement
+  NS_DECL_NSIDOMHTMLLEGENDELEMENT
+
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
   virtual void Focus(ErrorResult& aError) MOZ_OVERRIDE;
 
   virtual void PerformAccesskey(bool aKeyCausesActivation,
                                 bool aIsTrustedEvent) MOZ_OVERRIDE;
 
@@ -77,21 +81,17 @@ public:
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   /**
    * WebIDL Interface
    */
 
   already_AddRefed<HTMLFormElement> GetForm();
 
-  void GetAlign(nsAString& aAlign)
-  {
-    GetHTMLAttr(nsGkAtoms::align, aAlign);
-  }
-
+  // The XPCOM GetAlign is OK for us
   void SetAlign(const nsAString& aAlign, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
   }
 
   nsINode* GetParentObject() {
     Element* form = GetFormElement();
     return form ? static_cast<nsINode*>(form)
--- a/content/html/content/src/HTMLMeterElement.cpp
+++ b/content/html/content/src/HTMLMeterElement.cpp
@@ -24,18 +24,21 @@ HTMLMeterElement::HTMLMeterElement(alrea
 HTMLMeterElement::~HTMLMeterElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLMeterElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLMeterElement, Element)
 
 
-NS_INTERFACE_MAP_BEGIN(HTMLMeterElement)
+NS_INTERFACE_TABLE_HEAD(HTMLMeterElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLMeterElement,
+                                nsIDOMHTMLMeterElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLMeterElement)
 
 
 nsEventStates
 HTMLMeterElement::IntrinsicState() const
 {
@@ -215,16 +218,98 @@ HTMLMeterElement::Optimum() const
 
   if (optimum <= min) {
     return min;
   }
 
   return std::min(optimum, max);
 }
 
+/*
+ * XPCOM methods
+ */
+
+NS_IMETHODIMP
+HTMLMeterElement::GetMin(double* aValue)
+{
+  *aValue = Min();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetMin(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::min, aValue);
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::GetMax(double* aValue)
+{
+  *aValue = Max();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetMax(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::max, aValue);
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::GetValue(double* aValue)
+{
+  *aValue = Value();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetValue(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::value, aValue);
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::GetLow(double* aValue)
+{
+  *aValue = Low();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetLow(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::low, aValue);
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::GetHigh(double* aValue)
+{
+  *aValue = High();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetHigh(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::high, aValue);
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::GetOptimum(double* aValue)
+{
+  *aValue = Optimum();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLMeterElement::SetOptimum(double aValue)
+{
+  return SetDoubleAttr(nsGkAtoms::optimum, aValue);
+}
+
 nsEventStates
 HTMLMeterElement::GetOptimumState() const
 {
   /*
    * If the optimum value is in [minimum, low[,
    *     return if the value is in optimal, suboptimal or sub-suboptimal region
    *
    * If the optimum value is in [low, high],
--- a/content/html/content/src/HTMLMeterElement.h
+++ b/content/html/content/src/HTMLMeterElement.h
@@ -2,28 +2,29 @@
 /* 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 mozilla_dom_HTMLMeterElement_h
 #define mozilla_dom_HTMLMeterElement_h
 
 #include "mozilla/Attributes.h"
+#include "nsIDOMHTMLMeterElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsEventStateManager.h"
 #include "nsAlgorithm.h"
 #include <algorithm>
 
 namespace mozilla {
 namespace dom {
 
 class HTMLMeterElement MOZ_FINAL : public nsGenericHTMLElement,
-                                   public nsIDOMHTMLElement
+                                   public nsIDOMHTMLMeterElement
 {
 public:
   HTMLMeterElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLMeterElement();
 
   /* nsISupports */
   NS_DECL_ISUPPORTS_INHERITED
 
@@ -31,67 +32,70 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   /* nsIDOMElement */
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   /* nsIDOMHTMLElement */
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  /* nsIDOMHTMLMeterElement */
+  NS_DECL_NSIDOMHTMLMETERELEMENT
+
   virtual nsEventStates IntrinsicState() const MOZ_OVERRIDE;
 
   nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
 
   bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
                       const nsAString& aValue, nsAttrValue& aResult) MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   // WebIDL
 
   /* @return the value */
   double Value() const;
   void SetValue(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::value, aValue);
+    aRv = SetValue(aValue);
   }
 
   /* @return the minimum value */
   double Min() const;
   void SetMin(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::min, aValue);
+    aRv = SetMin(aValue);
   }
 
   /* @return the maximum value */
   double Max() const;
   void SetMax(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::max, aValue);
+    aRv = SetMax(aValue);
   }
 
   /* @return the low value */
   double Low() const;
   void SetLow(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::low, aValue);
+    aRv = SetLow(aValue);
   }
 
   /* @return the high value */
   double High() const;
   void SetHigh(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::high, aValue);
+    aRv = SetHigh(aValue);
   }
 
   /* @return the optimum value */
   double Optimum() const;
   void SetOptimum(double aValue, ErrorResult& aRv)
   {
-    aRv = SetDoubleAttr(nsGkAtoms::optimum, aValue);
+    aRv = SetOptimum(aValue);
   }
 
 protected:
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
 private:
 
--- a/content/html/content/src/HTMLModElement.cpp
+++ b/content/html/content/src/HTMLModElement.cpp
@@ -21,23 +21,30 @@ HTMLModElement::~HTMLModElement()
 {
 }
 
 
 NS_IMPL_ADDREF_INHERITED(HTMLModElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLModElement, Element)
 
 // QueryInterface implementation for HTMLModElement
-NS_INTERFACE_MAP_BEGIN(HTMLModElement)
+NS_INTERFACE_TABLE_HEAD(HTMLModElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLModElement,
+                                nsIDOMHTMLModElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLModElement)
 
+
+NS_IMPL_URI_ATTR(HTMLModElement, Cite, cite)
+NS_IMPL_STRING_ATTR(HTMLModElement, DateTime, datetime)
+
 JSObject*
 HTMLModElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLModElementBinding::Wrap(aCx, aScope, this);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/src/HTMLModElement.h
+++ b/content/html/content/src/HTMLModElement.h
@@ -3,23 +3,24 @@
  * 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 mozilla_dom_HTMLModElement_h
 #define mozilla_dom_HTMLModElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLModElement.h"
 #include "nsGkAtoms.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLModElement MOZ_FINAL : public nsGenericHTMLElement,
-                                 public nsIDOMHTMLElement
+                                 public nsIDOMHTMLModElement
 {
 public:
   HTMLModElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLModElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
@@ -27,32 +28,32 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLModElement
+  NS_DECL_NSIDOMHTMLMODELEMENT
+
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   void GetCite(nsString& aCite)
   {
     GetHTMLURIAttr(nsGkAtoms::cite, aCite);
   }
   void SetCite(const nsAString& aCite, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::cite, aCite, aRv);
   }
-  void GetDateTime(nsAString& aDateTime)
-  {
-    GetHTMLAttr(nsGkAtoms::datetime, aDateTime);
-  }
+  // XPCOM GetDateTime is fine.
   void SetDateTime(const nsAString& aDateTime, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::datetime, aDateTime, aRv);
   }
 
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 };
--- a/content/html/content/src/HTMLOutputElement.cpp
+++ b/content/html/content/src/HTMLOutputElement.cpp
@@ -48,30 +48,39 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTokenList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLOutputElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLOutputElement, Element)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLOutputElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElement)
-  NS_INTERFACE_TABLE_INHERITED2(HTMLOutputElement,
+  NS_INTERFACE_TABLE_INHERITED3(HTMLOutputElement,
+                                nsIDOMHTMLOutputElement,
                                 nsIMutationObserver,
                                 nsIConstraintValidation)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLOutputElement)
 
-void
+
+NS_IMPL_STRING_ATTR(HTMLOutputElement, Name, name)
+
+// nsIConstraintValidation
+NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(HTMLOutputElement)
+
+NS_IMETHODIMP
 HTMLOutputElement::SetCustomValidity(const nsAString& aError)
 {
   nsIConstraintValidation::SetCustomValidity(aError);
 
   UpdateState(true);
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLOutputElement::Reset()
 {
   mValueModeFlag = eModeDefault;
   return nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
 }
@@ -135,41 +144,77 @@ HTMLOutputElement::BindToTree(nsIDocumen
   // might end up a in a novalidate form, and unlike other form
   // controls that on its own is enough to make change ui-valid state.
   // So just go ahead and update our state now.
   UpdateState(false);
 
   return rv;
 }
 
-void
-HTMLOutputElement::SetValue(const nsAString& aValue, ErrorResult& aRv)
+NS_IMETHODIMP
+HTMLOutputElement::GetForm(nsIDOMHTMLFormElement** aForm)
+{
+  return nsGenericHTMLFormElement::GetForm(aForm);
+}
+
+NS_IMETHODIMP
+HTMLOutputElement::GetType(nsAString& aType)
+{
+  aType.AssignLiteral("output");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLOutputElement::GetValue(nsAString& aValue)
+{
+  nsContentUtils::GetNodeTextContent(this, true, aValue);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLOutputElement::SetValue(const nsAString& aValue)
 {
   mValueModeFlag = eModeValue;
-  aRv = nsContentUtils::SetNodeTextContent(this, aValue, true);
+  return nsContentUtils::SetNodeTextContent(this, aValue, true);
 }
 
-void
-HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aRv)
+NS_IMETHODIMP
+HTMLOutputElement::GetDefaultValue(nsAString& aDefaultValue)
+{
+  aDefaultValue = mDefaultValue;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue)
 {
   mDefaultValue = aDefaultValue;
   if (mValueModeFlag == eModeDefault) {
-    aRv = nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
+    return nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
   }
+
+  return NS_OK;
 }
 
 nsDOMSettableTokenList*
 HTMLOutputElement::HtmlFor()
 {
   if (!mTokenList) {
     mTokenList = new nsDOMSettableTokenList(this, nsGkAtoms::_for);
   }
   return mTokenList;
 }
 
+NS_IMETHODIMP
+HTMLOutputElement::GetHtmlFor(nsISupports** aResult)
+{
+  NS_ADDREF(*aResult = HtmlFor());
+  return NS_OK;
+}
+
 void HTMLOutputElement::DescendantsChanged()
 {
   if (mValueModeFlag == eModeDefault) {
     nsContentUtils::GetNodeTextContent(this, true, mDefaultValue);
   }
 }
 
 // nsIMutationObserver
--- a/content/html/content/src/HTMLOutputElement.h
+++ b/content/html/content/src/HTMLOutputElement.h
@@ -3,24 +3,25 @@
  * 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 mozilla_dom_HTMLOutputElement_h
 #define mozilla_dom_HTMLOutputElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLOutputElement.h"
 #include "nsStubMutationObserver.h"
 #include "nsIConstraintValidation.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLOutputElement MOZ_FINAL : public nsGenericHTMLFormElement,
-                                    public nsIDOMHTMLElement,
+                                    public nsIDOMHTMLOutputElement,
                                     public nsStubMutationObserver,
                                     public nsIConstraintValidation
 {
 public:
   using nsIConstraintValidation::GetValidationMessage;
 
   HTMLOutputElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLOutputElement();
@@ -32,16 +33,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLOutputElement
+  NS_DECL_NSIDOMHTMLOUTPUTELEMENT
+
   // nsIFormControl
   NS_IMETHOD_(uint32_t) GetType() const { return NS_FORM_OUTPUT; }
   NS_IMETHOD Reset() MOZ_OVERRIDE;
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) MOZ_OVERRIDE;
 
   virtual bool IsDisabled() const MOZ_OVERRIDE { return false; }
 
   nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
@@ -70,50 +74,41 @@ public:
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   // WebIDL
   nsDOMSettableTokenList* HtmlFor();
   // nsGenericHTMLFormElement::GetForm is fine.
-  void GetName(nsAString& aName)
-  {
-    GetHTMLAttr(nsGkAtoms::name, aName);
-  }
-
+  using nsGenericHTMLFormElement::GetForm;
+  // XPCOM GetName is fine.
   void SetName(const nsAString& aName, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::name, aName, aRv);
   }
 
-  void GetType(nsAString& aType)
+  // XPCOM GetType is fine.
+  // XPCOM GetDefaultValue is fine.
+  void SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aRv)
   {
-    aType.AssignLiteral("output");
-  }
-
-  void GetDefaultValue(nsAString& aDefaultValue)
-  {
-    aDefaultValue = mDefaultValue;
+    aRv = SetDefaultValue(aDefaultValue);
   }
-
-  void SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aRv);
-
-  void GetValue(nsAString& aValue)
+  // XPCOM GetValue is fine.
+  void SetValue(const nsAString& aValue, ErrorResult& aRv)
   {
-    nsContentUtils::GetNodeTextContent(this, true, aValue);
+    aRv = SetValue(aValue);
   }
 
-  void SetValue(const nsAString& aValue, ErrorResult& aRv);
-
   // nsIConstraintValidation::WillValidate is fine.
   // nsIConstraintValidation::Validity() is fine.
   // nsIConstraintValidation::GetValidationMessage() is fine.
   // nsIConstraintValidation::CheckValidity() is fine.
-  void SetCustomValidity(const nsAString& aError);
+  using nsIConstraintValidation::CheckValidity;
+  // nsIConstraintValidation::SetCustomValidity() is fine.
 
 protected:
   enum ValueModeFlag {
     eModeDefault,
     eModeValue
   };
 
   ValueModeFlag                     mValueModeFlag;
--- a/content/html/content/src/HTMLProgressElement.cpp
+++ b/content/html/content/src/HTMLProgressElement.cpp
@@ -26,18 +26,21 @@ HTMLProgressElement::HTMLProgressElement
 HTMLProgressElement::~HTMLProgressElement()
 {
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLProgressElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLProgressElement, Element)
 
 
-NS_INTERFACE_MAP_BEGIN(HTMLProgressElement)
+NS_INTERFACE_TABLE_HEAD(HTMLProgressElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLProgressElement,
+                                nsIDOMHTMLProgressElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLProgressElement)
 
 
 nsEventStates
 HTMLProgressElement::IntrinsicState() const
 {
@@ -59,40 +62,77 @@ HTMLProgressElement::ParseAttribute(int3
       return aResult.ParseDoubleValue(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute,
                                               aValue, aResult);
 }
 
+NS_IMETHODIMP
+HTMLProgressElement::GetValue(double* aValue)
+{
+  *aValue = Value();
+  return NS_OK;
+}
+
 double
 HTMLProgressElement::Value() const
 {
   const nsAttrValue* attrValue = mAttrsAndChildren.GetAttr(nsGkAtoms::value);
   if (!attrValue || attrValue->Type() != nsAttrValue::eDoubleValue ||
       attrValue->GetDoubleValue() < 0.0) {
     return kDefaultValue;
   }
 
   return std::min(attrValue->GetDoubleValue(), Max());
 }
 
+NS_IMETHODIMP
+HTMLProgressElement::SetValue(double aValue)
+{
+  ErrorResult rv;
+  SetValue(aValue, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLProgressElement::GetMax(double* aValue)
+{
+  *aValue = Max();
+  return NS_OK;
+}
+
 double
 HTMLProgressElement::Max() const
 {
   const nsAttrValue* attrMax = mAttrsAndChildren.GetAttr(nsGkAtoms::max);
   if (!attrMax || attrMax->Type() != nsAttrValue::eDoubleValue ||
       attrMax->GetDoubleValue() <= 0.0) {
     return kDefaultMax;
   }
 
   return attrMax->GetDoubleValue();
 }
 
+NS_IMETHODIMP
+HTMLProgressElement::SetMax(double aValue)
+{
+  ErrorResult rv;
+  SetMax(aValue, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLProgressElement::GetPosition(double* aPosition)
+{
+  *aPosition = Position();
+  return NS_OK;
+}
+
 double
 HTMLProgressElement::Position() const
 {
   if (IsIndeterminate()) {
     return kIndeterminatePosition;
   }
 
   return Value() / Max();
--- a/content/html/content/src/HTMLProgressElement.h
+++ b/content/html/content/src/HTMLProgressElement.h
@@ -2,27 +2,28 @@
 /* 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 mozilla_dom_HTMLProgressElement_h
 #define mozilla_dom_HTMLProgressElement_h
 
 #include "mozilla/Attributes.h"
+#include "nsIDOMHTMLProgressElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsEventStateManager.h"
 #include <algorithm>
 
 namespace mozilla {
 namespace dom {
 
 class HTMLProgressElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLElement
+                                      public nsIDOMHTMLProgressElement
 {
 public:
   HTMLProgressElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~HTMLProgressElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
@@ -30,16 +31,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLProgressElement
+  NS_DECL_NSIDOMHTMLPROGRESSELEMENT
+
   nsEventStates IntrinsicState() const MOZ_OVERRIDE;
 
   nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
 
   bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
                         const nsAString& aValue, nsAttrValue& aResult) MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
--- a/content/html/content/src/HTMLSharedElement.cpp
+++ b/content/html/content/src/HTMLSharedElement.cpp
@@ -29,28 +29,38 @@ HTMLSharedElement::~HTMLSharedElement()
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLSharedElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLSharedElement, Element)
 
 // QueryInterface implementation for HTMLSharedElement
 NS_INTERFACE_MAP_BEGIN(HTMLSharedElement)
   NS_HTML_CONTENT_INTERFACES_AMBIGUOUS(nsGenericHTMLElement,
-                                       nsIDOMHTMLBaseElement)
+                                       nsIDOMHTMLParamElement)
+  NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLParamElement, param)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLBaseElement, base)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLDirectoryElement, dir)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLQuoteElement, q)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLQuoteElement, blockquote)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLHeadElement, head)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLHtmlElement, html)
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLSharedElement)
 
+// nsIDOMHTMLParamElement
+NS_IMPL_STRING_ATTR(HTMLSharedElement, Name, name)
+NS_IMPL_STRING_ATTR(HTMLSharedElement, Type, type)
+NS_IMPL_STRING_ATTR(HTMLSharedElement, Value, value)
+NS_IMPL_STRING_ATTR(HTMLSharedElement, ValueType, valuetype)
+
+// nsIDOMHTMLDirectoryElement
+NS_IMPL_BOOL_ATTR(HTMLSharedElement, Compact, compact)
+
 // nsIDOMHTMLQuoteElement
 NS_IMPL_URI_ATTR(HTMLSharedElement, Cite, cite)
 
 // nsIDOMHTMLHeadElement
 // Empty
 
 // nsIDOMHTMLHtmlElement
 NS_IMPL_STRING_ATTR(HTMLSharedElement, Version, version)
--- a/content/html/content/src/HTMLSharedElement.h
+++ b/content/html/content/src/HTMLSharedElement.h
@@ -1,32 +1,34 @@
 /* -*- 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/. */
 
 #ifndef mozilla_dom_HTMLSharedElement_h
 #define mozilla_dom_HTMLSharedElement_h
 
+#include "nsIDOMHTMLParamElement.h"
 #include "nsIDOMHTMLBaseElement.h"
 #include "nsIDOMHTMLDirectoryElement.h"
 #include "nsIDOMHTMLQuoteElement.h"
 #include "nsIDOMHTMLHeadElement.h"
 #include "nsIDOMHTMLHtmlElement.h"
 #include "nsGenericHTMLElement.h"
 
 #include "nsGkAtoms.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/Assertions.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLSharedElement MOZ_FINAL : public nsGenericHTMLElement,
+                                    public nsIDOMHTMLParamElement,
                                     public nsIDOMHTMLBaseElement,
                                     public nsIDOMHTMLDirectoryElement,
                                     public nsIDOMHTMLQuoteElement,
                                     public nsIDOMHTMLHeadElement,
                                     public nsIDOMHTMLHtmlElement
 {
 public:
   HTMLSharedElement(already_AddRefed<nsINodeInfo> aNodeInfo)
@@ -42,19 +44,25 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLParamElement
+  NS_DECL_NSIDOMHTMLPARAMELEMENT
+
   // nsIDOMHTMLBaseElement
   NS_DECL_NSIDOMHTMLBASEELEMENT
 
+  // nsIDOMHTMLDirectoryElement
+  NS_DECL_NSIDOMHTMLDIRECTORYELEMENT
+
   // nsIDOMHTMLQuoteElement
   NS_DECL_NSIDOMHTMLQUOTEELEMENT
 
   // nsIDOMHTMLHeadElement
   NS_DECL_NSIDOMHTMLHEADELEMENT
 
   // nsIDOMHTMLHtmlElement
   NS_DECL_NSIDOMHTMLHTMLELEMENT
@@ -85,17 +93,17 @@ public:
 
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE
   {
-    return static_cast<nsIDOMHTMLBaseElement*>(this);
+    return static_cast<nsIDOMHTMLParamElement*>(this);
   }
 
   // WebIDL API
   // HTMLParamElement
   void GetName(DOMString& aValue)
   {
     MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::param));
     GetHTMLAttr(nsGkAtoms::name, aValue);
--- a/content/html/content/src/HTMLSharedListElement.cpp
+++ b/content/html/content/src/HTMLSharedListElement.cpp
@@ -27,16 +27,17 @@ HTMLSharedListElement::~HTMLSharedListEl
 NS_IMPL_ADDREF_INHERITED(HTMLSharedListElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLSharedListElement, Element)
 
 // QueryInterface implementation for nsHTMLSharedListElement
 NS_INTERFACE_MAP_BEGIN(HTMLSharedListElement)
   NS_HTML_CONTENT_INTERFACES_AMBIGUOUS(nsGenericHTMLElement,
                                        nsIDOMHTMLOListElement)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLOListElement, ol)
+  NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLDListElement, dl)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLUListElement, ul)
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLSharedListElement)
 
 
 NS_IMPL_BOOL_ATTR(HTMLSharedListElement, Compact, compact)
--- a/content/html/content/src/HTMLSharedListElement.h
+++ b/content/html/content/src/HTMLSharedListElement.h
@@ -4,24 +4,26 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_HTMLSharedListElement_h
 #define mozilla_dom_HTMLSharedListElement_h
 #include "mozilla/Attributes.h"
 #include "mozilla/Util.h"
 
 #include "nsIDOMHTMLOListElement.h"
+#include "nsIDOMHTMLDListElement.h"
 #include "nsIDOMHTMLUListElement.h"
 #include "nsGenericHTMLElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLSharedListElement MOZ_FINAL : public nsGenericHTMLElement,
                                         public nsIDOMHTMLOListElement,
+                                        public nsIDOMHTMLDListElement,
                                         public nsIDOMHTMLUListElement
 {
 public:
   HTMLSharedListElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLSharedListElement();
@@ -36,16 +38,19 @@ public:
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
   // nsIDOMHTMLOListElement
   NS_DECL_NSIDOMHTMLOLISTELEMENT
 
+  // nsIDOMHTMLDListElement
+  // fully declared by NS_DECL_NSIDOMHTMLOLISTELEMENT
+
   // nsIDOMHTMLUListElement
   // fully declared by NS_DECL_NSIDOMHTMLOLISTELEMENT
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) MOZ_OVERRIDE;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
--- a/content/html/content/src/HTMLTableCellElement.cpp
+++ b/content/html/content/src/HTMLTableCellElement.cpp
@@ -29,18 +29,21 @@ HTMLTableCellElement::WrapNode(JSContext
 {
   return HTMLTableCellElementBinding::Wrap(aCx, aScope, this);
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableCellElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableCellElement, Element)
 
 // QueryInterface implementation for HTMLTableCellElement
-NS_INTERFACE_MAP_BEGIN(HTMLTableCellElement)
+NS_INTERFACE_TABLE_HEAD(HTMLTableCellElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLTableCellElement,
+                                nsIDOMHTMLTableCellElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableCellElement)
 
 
 // protected method
 HTMLTableRowElement*
@@ -97,31 +100,270 @@ HTMLTableCellElement::CellIndex() const
       return i;
     }
   }
 
   return -1;
 }
 
 NS_IMETHODIMP
+HTMLTableCellElement::GetCellIndex(int32_t* aCellIndex)
+{
+  *aCellIndex = CellIndex();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 HTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
 {
   nsresult rv = nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (HTMLTableElement* table = GetTable()) {
     nsMappedAttributes* tableInheritedAttributes =
       table->GetAttributesMappedForCell();
     if (tableInheritedAttributes) {
       aRuleWalker->Forward(tableInheritedAttributes);
     }
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP
+HTMLTableCellElement::SetAbbr(const nsAString& aAbbr)
+{
+  ErrorResult rv;
+  SetAbbr(aAbbr, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetAbbr(nsAString& aAbbr)
+{
+  nsString abbr;
+  GetAbbr(abbr);
+  aAbbr = abbr;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetAxis(const nsAString& aAxis)
+{
+  ErrorResult rv;
+  SetAxis(aAxis, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetAxis(nsAString& aAxis)
+{
+  nsString axis;
+  GetAxis(axis);
+  aAxis = axis;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetAlign(const nsAString& aAlign)
+{
+  ErrorResult rv;
+  SetAlign(aAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetAlign(nsAString& aAlign)
+{
+  nsString align;
+  GetAlign(align);
+  aAlign = align;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetVAlign(const nsAString& aVAlign)
+{
+  ErrorResult rv;
+  SetVAlign(aVAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetVAlign(nsAString& aVAlign)
+{
+  nsString vAlign;
+  GetVAlign(vAlign);
+  aVAlign = vAlign;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetCh(const nsAString& aCh)
+{
+  ErrorResult rv;
+  SetCh(aCh, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetCh(nsAString& aCh)
+{
+  nsString ch;
+  GetCh(ch);
+  aCh = ch;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetChOff(const nsAString& aChOff)
+{
+  ErrorResult rv;
+  SetChOff(aChOff, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetChOff(nsAString& aChOff)
+{
+  nsString chOff;
+  GetChOff(chOff);
+  aChOff = chOff;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetBgColor(const nsAString& aBgColor)
+{
+  ErrorResult rv;
+  SetBgColor(aBgColor, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetBgColor(nsAString& aBgColor)
+{
+  nsString bgColor;
+  GetBgColor(bgColor);
+  aBgColor = bgColor;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetHeight(const nsAString& aHeight)
+{
+  ErrorResult rv;
+  SetHeight(aHeight, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetHeight(nsAString& aHeight)
+{
+  nsString height;
+  GetHeight(height);
+  aHeight = height;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetWidth(const nsAString& aWidth)
+{
+  ErrorResult rv;
+  SetWidth(aWidth, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetWidth(nsAString& aWidth)
+{
+  nsString width;
+  GetWidth(width);
+  aWidth = width;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetNoWrap(bool aNoWrap)
+{
+  ErrorResult rv;
+  SetNoWrap(aNoWrap, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetNoWrap(bool* aNoWrap)
+{
+  *aNoWrap = NoWrap();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetScope(const nsAString& aScope)
+{
+  ErrorResult rv;
+  SetScope(aScope, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetScope(nsAString& aScope)
+{
+  nsString scope;
+  GetScope(scope);
+  aScope = scope;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetHeaders(const nsAString& aHeaders)
+{
+  ErrorResult rv;
+  SetHeaders(aHeaders, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetHeaders(nsAString& aHeaders)
+{
+  nsString headers;
+  GetHeaders(headers);
+  aHeaders = headers;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetColSpan(int32_t aColSpan)
+{
+  ErrorResult rv;
+  SetColSpan(aColSpan, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetColSpan(int32_t* aColSpan)
+{
+  *aColSpan = ColSpan();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::SetRowSpan(int32_t aRowSpan)
+{
+  ErrorResult rv;
+  SetRowSpan(aRowSpan, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableCellElement::GetRowSpan(int32_t* aRowSpan)
+{
+  *aRowSpan = RowSpan();
+  return NS_OK;
+}
+
 void
 HTMLTableCellElement::GetAlign(nsString& aValue)
 {
   if (!GetAttr(kNameSpaceID_None, nsGkAtoms::align, aValue)) {
     // There's no align attribute, ask the row for the alignment.
     HTMLTableRowElement* row = GetRow();
     if (row) {
       row->GetAlign(aValue);
@@ -197,17 +439,17 @@ HTMLTableCellElement::ParseAttribute(int
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static
+static 
 void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                            nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
     // width: value
     nsCSSValue* width = aData->ValueForWidth();
     if (width->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
--- a/content/html/content/src/HTMLTableCellElement.h
+++ b/content/html/content/src/HTMLTableCellElement.h
@@ -2,24 +2,27 @@
 /* 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 mozilla_dom_HTMLTableCellElement_h
 #define mozilla_dom_HTMLTableCellElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLTableCellElement.h"
+
+class nsIDOMHTMLTableRowElement;
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTableElement;
 
 class HTMLTableCellElement MOZ_FINAL : public nsGenericHTMLElement,
-                                       public nsIDOMHTMLElement
+                                       public nsIDOMHTMLTableCellElement
 {
 public:
   HTMLTableCellElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLTableCellElement();
 
@@ -30,16 +33,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLTableCellElement
+  NS_DECL_NSIDOMHTMLTABLECELLELEMENT
+
   uint32_t ColSpan() const
   {
     return GetIntAttr(nsGkAtoms::colspan, 1);
   }
   void SetColSpan(uint32_t aColSpan, ErrorResult& aError)
   {
     SetHTMLIntAttr(nsGkAtoms::colspan, aColSpan, aError);
   }
--- a/content/html/content/src/HTMLTableColElement.cpp
+++ b/content/html/content/src/HTMLTableColElement.cpp
@@ -29,22 +29,125 @@ HTMLTableColElement::WrapNode(JSContext 
 {
   return HTMLTableColElementBinding::Wrap(aCx, aScope, this);
 }
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableColElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableColElement, Element)
 
 // QueryInterface implementation for HTMLTableColElement
-NS_INTERFACE_MAP_BEGIN(HTMLTableColElement)
+NS_INTERFACE_TABLE_HEAD(HTMLTableColElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLTableColElement,
+                                nsIDOMHTMLTableColElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableColElement)
 
+NS_IMETHODIMP
+HTMLTableColElement::SetSpan(int32_t aSpan)
+{
+  ErrorResult rv;
+  SetSpan(aSpan, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetSpan(int32_t* aSpan)
+{
+  *aSpan = Span();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::SetAlign(const nsAString& aAlign)
+{
+  ErrorResult rv;
+  SetAlign(aAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetAlign(nsAString& aAlign)
+{
+  nsString align;
+  GetAlign(align);
+  aAlign = align;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::SetVAlign(const nsAString& aVAlign)
+{
+  ErrorResult rv;
+  SetVAlign(aVAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetVAlign(nsAString& aVAlign)
+{
+  nsString vAlign;
+  GetVAlign(vAlign);
+  aVAlign = vAlign;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::SetCh(const nsAString& aCh)
+{
+  ErrorResult rv;
+  SetCh(aCh, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetCh(nsAString& aCh)
+{
+  nsString ch;
+  GetCh(ch);
+  aCh = ch;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::SetChOff(const nsAString& aChOff)
+{
+  ErrorResult rv;
+  SetChOff(aChOff, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetChOff(nsAString& aChOff)
+{
+  nsString chOff;
+  GetChOff(chOff);
+  aChOff = chOff;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::SetWidth(const nsAString& aWidth)
+{
+  ErrorResult rv;
+  SetWidth(aWidth, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableColElement::GetWidth(nsAString& aWidth)
+{
+  nsString width;
+  GetWidth(width);
+  aWidth = width;
+  return NS_OK;
+}
+
 bool
 HTMLTableColElement::ParseAttribute(int32_t aNamespaceID,
                                     nsIAtom* aAttribute,
                                     const nsAString& aValue,
                                     nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     /* ignore these attributes, stored simply as strings ch */
--- a/content/html/content/src/HTMLTableColElement.h
+++ b/content/html/content/src/HTMLTableColElement.h
@@ -2,22 +2,23 @@
 /* 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 mozilla_dom_HTMLTableColElement_h
 #define mozilla_dom_HTMLTableColElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLTableColElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTableColElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLElement
+                                      public nsIDOMHTMLTableColElement
 {
 public:
   HTMLTableColElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
   virtual ~HTMLTableColElement();
 
@@ -28,16 +29,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLTableColElement
+  NS_DECL_NSIDOMHTMLTABLECOLELEMENT
+
   uint32_t Span() const
   {
     return GetIntAttr(nsGkAtoms::span, 1);
   }
   void SetSpan(uint32_t aSpan, ErrorResult& aError)
   {
     SetHTMLIntAttr(nsGkAtoms::span, aSpan, aError);
   }
--- a/content/html/content/src/HTMLTableElement.cpp
+++ b/content/html/content/src/HTMLTableElement.cpp
@@ -1,16 +1,17 @@
 /* -*- 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/. */
 
 #include "mozilla/Util.h"
 
 #include "mozilla/dom/HTMLTableElement.h"
+#include "nsIDOMHTMLTableSectionElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsRuleData.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsMappedAttributes.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 #include "mozilla/dom/HTMLTableElementBinding.h"
 #include "nsContentUtils.h"
@@ -338,26 +339,246 @@ NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableElement)
 
 
 // the DOM spec says border, cellpadding, cellSpacing are all "wstring"
 // in fact, they are integers or they are meaningless.  so we store them
 // here as ints.
 
+NS_IMETHODIMP
+HTMLTableElement::SetAlign(const nsAString& aAlign)
+{
+  ErrorResult rv;
+  SetAlign(aAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetAlign(nsAString& aAlign)
+{
+  nsString align;
+  GetAlign(align);
+  aAlign = align;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetBgColor(const nsAString& aBgColor)
+{
+  ErrorResult rv;
+  SetBgColor(aBgColor, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetBgColor(nsAString& aBgColor)
+{
+  nsString bgColor;
+  GetBgColor(bgColor);
+  aBgColor = bgColor;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetBorder(const nsAString& aBorder)
+{
+  ErrorResult rv;
+  SetBorder(aBorder, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetBorder(nsAString& aBorder)
+{
+  nsString border;
+  GetBorder(border);
+  aBorder = border;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetCellPadding(const nsAString& aCellPadding)
+{
+  ErrorResult rv;
+  SetCellPadding(aCellPadding, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetCellPadding(nsAString& aCellPadding)
+{
+  nsString cellPadding;
+  GetCellPadding(cellPadding);
+  aCellPadding = cellPadding;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetCellSpacing(const nsAString& aCellSpacing)
+{
+  ErrorResult rv;
+  SetCellSpacing(aCellSpacing, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetCellSpacing(nsAString& aCellSpacing)
+{
+  nsString cellSpacing;
+  GetCellSpacing(cellSpacing);
+  aCellSpacing = cellSpacing;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetFrame(const nsAString& aFrame)
+{
+  ErrorResult rv;
+  SetFrame(aFrame, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetFrame(nsAString& aFrame)
+{
+  nsString frame;
+  GetFrame(frame);
+  aFrame = frame;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetRules(const nsAString& aRules)
+{
+  ErrorResult rv;
+  SetRules(aRules, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetRules(nsAString& aRules)
+{
+  nsString rules;
+  GetRules(rules);
+  aRules = rules;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetSummary(const nsAString& aSummary)
+{
+  ErrorResult rv;
+  SetSummary(aSummary, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetSummary(nsAString& aSummary)
+{
+  nsString summary;
+  GetSummary(summary);
+  aSummary = summary;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetWidth(const nsAString& aWidth)
+{
+  ErrorResult rv;
+  SetWidth(aWidth, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetWidth(nsAString& aWidth)
+{
+  nsString width;
+  GetWidth(width);
+  aWidth = width;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetCaption(nsIDOMHTMLTableCaptionElement** aValue)
+{
+  nsCOMPtr<nsIDOMHTMLTableCaptionElement> caption = GetCaption();
+  caption.forget(aValue);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetCaption(nsIDOMHTMLTableCaptionElement* aValue)
+{
+  HTMLTableCaptionElement* caption =
+    static_cast<HTMLTableCaptionElement*>(aValue);
+  SetCaption(caption);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetTHead(nsIDOMHTMLTableSectionElement** aValue)
+{
+  NS_IF_ADDREF(*aValue = GetTHead());
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetTHead(nsIDOMHTMLTableSectionElement* aValue)
+{
+  HTMLTableSectionElement* section =
+    static_cast<HTMLTableSectionElement*>(aValue);
+  ErrorResult rv;
+  SetTHead(section, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetTFoot(nsIDOMHTMLTableSectionElement** aValue)
+{
+  NS_IF_ADDREF(*aValue = GetTFoot());
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableElement::SetTFoot(nsIDOMHTMLTableSectionElement* aValue)
+{
+  HTMLTableSectionElement* section =
+    static_cast<HTMLTableSectionElement*>(aValue);
+  ErrorResult rv;
+  SetTFoot(section, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableElement::GetRows(nsIDOMHTMLCollection** aValue)
+{
+  NS_ADDREF(*aValue = Rows());
+  return NS_OK;
+}
+
 nsIHTMLCollection*
 HTMLTableElement::Rows()
 {
   if (!mRows) {
     mRows = new TableRowsCollection(this);
   }
 
   return mRows;
 }
 
+NS_IMETHODIMP
+HTMLTableElement::GetTBodies(nsIDOMHTMLCollection** aValue)
+{
+  NS_ADDREF(*aValue = TBodies());
+  return NS_OK;
+}
+
 nsIHTMLCollection*
 HTMLTableElement::TBodies()
 {
   if (!mTBodies) {
     // Not using NS_GetContentList because this should not be cached
     mTBodies = new nsContentList(this,
                                  kNameSpaceID_XHTML,
                                  nsGkAtoms::tbody,
@@ -384,25 +605,34 @@ HTMLTableElement::CreateTHead()
     }
 
     ErrorResult rv;
     nsINode::InsertBefore(*head, nsINode::GetFirstChild(), rv);
   }
   return head.forget();
 }
 
-void
+NS_IMETHODIMP
+HTMLTableElement::CreateTHead(nsIDOMHTMLElement** aValue)
+{
+  nsRefPtr<nsGenericHTMLElement> thead = CreateTHead();
+  return thead ? CallQueryInterface(thead, aValue) : NS_OK;
+}
+
+NS_IMETHODIMP
 HTMLTableElement::DeleteTHead()
 {
   HTMLTableSectionElement* tHead = GetTHead();
   if (tHead) {
     mozilla::ErrorResult rv;
     nsINode::RemoveChild(*tHead, rv);
     MOZ_ASSERT(!rv.Failed());
   }
+
+  return NS_OK;
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::CreateTFoot()
 {
   nsRefPtr<nsGenericHTMLElement> foot = GetTFoot();
   if (!foot) {
     // create a new foot rowgroup
@@ -415,25 +645,34 @@ HTMLTableElement::CreateTFoot()
       return nullptr;
     }
     AppendChildTo(foot, true);
   }
 
   return foot.forget();
 }
 
-void
+NS_IMETHODIMP
+HTMLTableElement::CreateTFoot(nsIDOMHTMLElement** aValue)
+{
+  nsRefPtr<nsGenericHTMLElement> tfoot = CreateTFoot();
+  return tfoot ? CallQueryInterface(tfoot, aValue) : NS_OK;
+}
+
+NS_IMETHODIMP
 HTMLTableElement::DeleteTFoot()
 {
   HTMLTableSectionElement* tFoot = GetTFoot();
   if (tFoot) {
     mozilla::ErrorResult rv;
     nsINode::RemoveChild(*tFoot, rv);
     MOZ_ASSERT(!rv.Failed());
   }
+
+  return NS_OK;
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::CreateCaption()
 {
   nsRefPtr<nsGenericHTMLElement> caption = GetCaption();
   if (!caption) {
     // Create a new caption.
@@ -446,25 +685,34 @@ HTMLTableElement::CreateCaption()
       return nullptr;
     }
 
     AppendChildTo(caption, true);
   }
   return caption.forget();
 }
 
-void
+NS_IMETHODIMP
+HTMLTableElement::CreateCaption(nsIDOMHTMLElement** aValue)
+{
+  nsRefPtr<nsGenericHTMLElement> caption = CreateCaption();
+  return caption ? CallQueryInterface(caption, aValue) : NS_OK;
+}
+
+NS_IMETHODIMP
 HTMLTableElement::DeleteCaption()
 {
   HTMLTableCaptionElement* caption = GetCaption();
   if (caption) {
     mozilla::ErrorResult rv;
     nsINode::RemoveChild(*caption, rv);
     MOZ_ASSERT(!rv.Failed());
   }
+
+  return NS_OK;
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::CreateTBody()
 {
   nsCOMPtr<nsINodeInfo> nodeInfo =
     OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::tbody, nullptr,
                                                kNameSpaceID_XHTML,
@@ -490,17 +738,17 @@ HTMLTableElement::CreateTBody()
 
   return newBody.forget();
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::InsertRow(int32_t aIndex, ErrorResult& aError)
 {
   /* get the ref row at aIndex
-     if there is one,
+     if there is one, 
        get its parent
        insert the new row just before the ref row
      else
        get the first row group
        insert the new row as its first child
   */
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
@@ -595,16 +843,24 @@ HTMLTableElement::InsertRow(int32_t aInd
         rowGroup->InsertBefore(*newRow, rows->Item(0), aError);
       }
     }
   }
 
   return newRow.forget();
 }
 
+NS_IMETHODIMP
+HTMLTableElement::InsertRow(int32_t aIndex, nsIDOMHTMLElement** aValue)
+{
+  ErrorResult rv;
+  nsRefPtr<nsGenericHTMLElement> newRow = InsertRow(aIndex, rv);
+  return rv.Failed() ? rv.ErrorCode() : CallQueryInterface(newRow, aValue);
+}
+
 void
 HTMLTableElement::DeleteRow(int32_t aIndex, ErrorResult& aError)
 {
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
@@ -625,16 +881,24 @@ HTMLTableElement::DeleteRow(int32_t aInd
   if (!row) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   row->RemoveFromParent();
 }
 
+NS_IMETHODIMP
+HTMLTableElement::DeleteRow(int32_t aValue)
+{
+  ErrorResult rv;
+  DeleteRow(aValue, rv);
+  return rv.ErrorCode();
+}
+
 static const nsAttrValue::EnumTable kFrameTable[] = {
   { "void",   NS_STYLE_TABLE_FRAME_NONE },
   { "above",  NS_STYLE_TABLE_FRAME_ABOVE },
   { "below",  NS_STYLE_TABLE_FRAME_BELOW },
   { "hsides", NS_STYLE_TABLE_FRAME_HSIDES },
   { "lhs",    NS_STYLE_TABLE_FRAME_LEFT },
   { "rhs",    NS_STYLE_TABLE_FRAME_RIGHT },
   { "vsides", NS_STYLE_TABLE_FRAME_VSIDES },
--- a/content/html/content/src/HTMLTableElement.h
+++ b/content/html/content/src/HTMLTableElement.h
@@ -34,35 +34,33 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLTableElement
+  NS_DECL_NSIDOMHTMLTABLEELEMENT
+
   HTMLTableCaptionElement* GetCaption() const
   {
     return static_cast<HTMLTableCaptionElement*>(GetChild(nsGkAtoms::caption));
   }
   void SetCaption(HTMLTableCaptionElement* aCaption)
   {
     DeleteCaption();
     if (aCaption) {
       mozilla::ErrorResult rv;
       nsINode::AppendChild(*aCaption, rv);
     }
   }
-
-  void DeleteTFoot();
-
   already_AddRefed<nsGenericHTMLElement> CreateCaption();
 
-  void DeleteCaption();
-
   HTMLTableSectionElement* GetTHead() const
   {
     return static_cast<HTMLTableSectionElement*>(GetChild(nsGkAtoms::thead));
   }
   void SetTHead(HTMLTableSectionElement* aTHead, ErrorResult& aError)
   {
     if (aTHead && !aTHead->IsHTML(nsGkAtoms::thead)) {
       aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
@@ -71,18 +69,16 @@ public:
 
     DeleteTHead();
     if (aTHead) {
       nsINode::InsertBefore(*aTHead, nsINode::GetFirstChild(), aError);
     }
   }
   already_AddRefed<nsGenericHTMLElement> CreateTHead();
 
-  void DeleteTHead();
-
   HTMLTableSectionElement* GetTFoot() const
   {
     return static_cast<HTMLTableSectionElement*>(GetChild(nsGkAtoms::tfoot));
   }
   void SetTFoot(HTMLTableSectionElement* aTFoot, ErrorResult& aError)
   {
     if (aTFoot && !aTFoot->IsHTML(nsGkAtoms::tfoot)) {
       aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
--- a/content/html/content/src/HTMLTableRowElement.cpp
+++ b/content/html/content/src/HTMLTableRowElement.cpp
@@ -30,35 +30,34 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCells)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableRowElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableRowElement, Element)
 
 // QueryInterface implementation for HTMLTableRowElement
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTableRowElement)
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLTableRowElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLTableRowElement,
+                                nsIDOMHTMLTableRowElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableRowElement)
 
 
 // protected method
-HTMLTableSectionElement*
+already_AddRefed<nsIDOMHTMLTableSectionElement>
 HTMLTableRowElement::GetSection() const
 {
-  nsIContent* parent = GetParent();
-  if (parent->IsHTML() && (parent->Tag() == nsGkAtoms::thead ||
-                           parent->Tag() == nsGkAtoms::tbody ||
-                           parent->Tag() == nsGkAtoms::tfoot)) {
-    return static_cast<HTMLTableSectionElement*>(parent);
-  }
-  return nullptr;
+  nsCOMPtr<nsIDOMHTMLTableSectionElement> section =
+    do_QueryInterface(GetParent());
+  return section.forget();
 }
 
 // protected method
 HTMLTableElement*
 HTMLTableRowElement::GetTable() const
 {
   nsIContent* parent = GetParent();
   if (!parent) {
@@ -90,35 +89,52 @@ HTMLTableRowElement::RowIndex() const
     if (rows->GetElementAt(i) == this) {
       return i;
     }
   }
 
   return -1;
 }
 
+NS_IMETHODIMP
+HTMLTableRowElement::GetRowIndex(int32_t* aValue)
+{
+  *aValue = RowIndex();
+  return NS_OK;
+}
+
 int32_t
 HTMLTableRowElement::SectionRowIndex() const
 {
-  HTMLTableSectionElement* section = GetSection();
+  nsCOMPtr<nsIDOMHTMLTableSectionElement> section = GetSection();
   if (!section) {
     return -1;
   }
 
-  nsCOMPtr<nsIHTMLCollection> coll = section->Rows();
+  nsCOMPtr<nsIDOMHTMLCollection> rows;
+  section->GetRows(getter_AddRefs(rows));
+
+  nsCOMPtr<nsIHTMLCollection> coll = do_QueryInterface(rows);
   uint32_t numRows = coll->Length();
   for (uint32_t i = 0; i < numRows; i++) {
     if (coll->GetElementAt(i) == this) {
       return i;
     }
   }
 
   return -1;
 }
 
+NS_IMETHODIMP
+HTMLTableRowElement::GetSectionRowIndex(int32_t* aValue)
+{
+  *aValue = SectionRowIndex();
+  return NS_OK;
+}
+
 static bool
 IsCell(nsIContent *aContent, int32_t aNamespaceID,
        nsIAtom* aAtom, void *aData)
 {
   nsIAtom* tag = aContent->Tag();
 
   return ((tag == nsGkAtoms::td || tag == nsGkAtoms::th) &&
           aContent->IsHTML());
@@ -136,16 +152,23 @@ HTMLTableRowElement::Cells()
                                nullptr,
                                kNameSpaceID_XHTML,
                                false);
   }
 
   return mCells;
 }
 
+NS_IMETHODIMP
+HTMLTableRowElement::GetCells(nsIDOMHTMLCollection** aValue)
+{
+  NS_ADDREF(*aValue = Cells());
+  return NS_OK;
+}
+
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableRowElement::InsertCell(int32_t aIndex,
                                 ErrorResult& aError)
 {
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return nullptr;
   }
@@ -183,16 +206,24 @@ HTMLTableRowElement::InsertCell(int32_t 
     return nullptr;
   }
 
   nsINode::InsertBefore(*cell, nextSibling, aError);
 
   return cell.forget();
 }
 
+NS_IMETHODIMP
+HTMLTableRowElement::InsertCell(int32_t aIndex, nsIDOMHTMLElement** aValue)
+{
+  ErrorResult rv;
+  nsRefPtr<nsGenericHTMLElement> cell = InsertCell(aIndex, rv);
+  return rv.Failed() ? rv.ErrorCode() : CallQueryInterface(cell, aValue);
+}
+
 void
 HTMLTableRowElement::DeleteCell(int32_t aValue, ErrorResult& aError)
 {
   if (aValue < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
@@ -215,16 +246,109 @@ HTMLTableRowElement::DeleteCell(int32_t 
   if (!cell) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   nsINode::RemoveChild(*cell, aError);
 }
 
+NS_IMETHODIMP
+HTMLTableRowElement::DeleteCell(int32_t aValue)
+{
+  ErrorResult rv;
+  DeleteCell(aValue, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::SetAlign(const nsAString& aAlign)
+{
+  ErrorResult rv;
+  SetAlign(aAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::GetAlign(nsAString& aAlign)
+{
+  nsString align;
+  GetAlign(align);
+  aAlign = align;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::SetVAlign(const nsAString& aVAlign)
+{
+  ErrorResult rv;
+  SetVAlign(aVAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::GetVAlign(nsAString& aVAlign)
+{
+  nsString vAlign;
+  GetVAlign(vAlign);
+  aVAlign = vAlign;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::SetCh(const nsAString& aCh)
+{
+  ErrorResult rv;
+  SetCh(aCh, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::GetCh(nsAString& aCh)
+{
+  nsString ch;
+  GetCh(ch);
+  aCh = ch;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::SetChOff(const nsAString& aChOff)
+{
+  ErrorResult rv;
+  SetChOff(aChOff, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::GetChOff(nsAString& aChOff)
+{
+  nsString chOff;
+  GetChOff(chOff);
+  aChOff = chOff;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::SetBgColor(const nsAString& aBgColor)
+{
+  ErrorResult rv;
+  SetBgColor(aBgColor, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableRowElement::GetBgColor(nsAString& aBgColor)
+{
+  nsString bgColor;
+  GetBgColor(bgColor);
+  aBgColor = bgColor;
+  return NS_OK;
+}
+
 bool
 HTMLTableRowElement::ParseAttribute(int32_t aNamespaceID,
                                     nsIAtom* aAttribute,
                                     const nsAString& aValue,
                                     nsAttrValue& aResult)
 {
   /*
    * ignore these attributes, stored simply as strings
--- a/content/html/content/src/HTMLTableRowElement.h
+++ b/content/html/content/src/HTMLTableRowElement.h
@@ -2,27 +2,27 @@
 /* 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 mozilla_dom_HTMLTableRowElement_h
 #define mozilla_dom_HTMLTableRowElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLTableRowElement.h"
 
 class nsIDOMHTMLTableElement;
+class nsIDOMHTMLTableSectionElement;
 class nsContentList;
 
 namespace mozilla {
 namespace dom {
 
-class HTMLTableSectionElement;
-
 class HTMLTableRowElement MOZ_FINAL : public nsGenericHTMLElement,
-                                      public nsIDOMHTMLElement
+                                      public nsIDOMHTMLTableRowElement
 {
 public:
   HTMLTableRowElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLTableRowElement, tr)
@@ -34,16 +34,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLTableRowElement
+  NS_DECL_NSIDOMHTMLTABLEROWELEMENT
+
   int32_t RowIndex() const;
   int32_t SectionRowIndex() const;
   nsIHTMLCollection* Cells();
   already_AddRefed<nsGenericHTMLElement>
     InsertCell(int32_t aIndex, ErrorResult& aError);
   void DeleteCell(int32_t aValue, ErrorResult& aError);
 
   void GetAlign(nsString& aAlign)
@@ -100,17 +103,17 @@ public:
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLTableRowElement,
                                                      nsGenericHTMLElement)
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
-  HTMLTableSectionElement* GetSection() const;
+  already_AddRefed<nsIDOMHTMLTableSectionElement> GetSection() const;
   HTMLTableElement* GetTable() const;
   nsRefPtr<nsContentList> mCells;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableRowElement_h */
--- a/content/html/content/src/HTMLTableSectionElement.cpp
+++ b/content/html/content/src/HTMLTableSectionElement.cpp
@@ -30,37 +30,115 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRows)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableSectionElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableSectionElement, Element)
 
 // QueryInterface implementation for HTMLTableSectionElement
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTableSectionElement)
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLTableSectionElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLTableSectionElement,
+                                nsIDOMHTMLTableSectionElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableSectionElement)
 
+NS_IMETHODIMP
+HTMLTableSectionElement::SetAlign(const nsAString& aAlign)
+{
+  ErrorResult rv;
+  SetAlign(aAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::GetAlign(nsAString& aAlign)
+{
+  nsString align;
+  GetAlign(align);
+  aAlign = align;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::SetVAlign(const nsAString& aVAlign)
+{
+  ErrorResult rv;
+  SetVAlign(aVAlign, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::GetVAlign(nsAString& aVAlign)
+{
+  nsString vAlign;
+  GetVAlign(vAlign);
+  aVAlign = vAlign;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::SetCh(const nsAString& aCh)
+{
+  ErrorResult rv;
+  SetCh(aCh, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::GetCh(nsAString& aCh)
+{
+  nsString ch;
+  GetCh(ch);
+  aCh = ch;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::SetChOff(const nsAString& aChOff)
+{
+  ErrorResult rv;
+  SetChOff(aChOff, rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLTableSectionElement::GetChOff(nsAString& aChOff)
+{
+  nsString chOff;
+  GetChOff(chOff);
+  aChOff = chOff;
+  return NS_OK;
+}
+
 nsIHTMLCollection*
 HTMLTableSectionElement::Rows()
 {
   if (!mRows) {
     mRows = new nsContentList(this,
                               mNodeInfo->NamespaceID(),
                               nsGkAtoms::tr,
                               nsGkAtoms::tr,
                               false);
   }
 
   return mRows;
 }
 
+NS_IMETHODIMP
+HTMLTableSectionElement::GetRows(nsIDOMHTMLCollection** aValue)
+{
+  NS_ADDREF(*aValue = Rows());
+  return NS_OK;
+}
+
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableSectionElement::InsertRow(int32_t aIndex, ErrorResult& aError)
 {
   if (aIndex < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return nullptr;
   }
 
@@ -89,16 +167,25 @@ HTMLTableSectionElement::InsertRow(int32
   if (doInsert) {
     nsINode::InsertBefore(*rowContent, rows->Item(aIndex), aError);
   } else {
     nsINode::AppendChild(*rowContent, aError);
   }
   return rowContent.forget();
 }
 
+NS_IMETHODIMP
+HTMLTableSectionElement::InsertRow(int32_t aIndex,
+                                   nsIDOMHTMLElement** aValue)
+{
+  ErrorResult rv;
+  nsRefPtr<nsGenericHTMLElement> row = InsertRow(aIndex, rv);
+  return rv.Failed() ? rv.ErrorCode() : CallQueryInterface(row, aValue);
+}
+
 void
 HTMLTableSectionElement::DeleteRow(int32_t aValue, ErrorResult& aError)
 {
   if (aValue < -1) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
@@ -121,16 +208,24 @@ HTMLTableSectionElement::DeleteRow(int32
   if (!row) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   nsINode::RemoveChild(*row, aError);
 }
 
+NS_IMETHODIMP
+HTMLTableSectionElement::DeleteRow(int32_t aValue)
+{
+  ErrorResult rv;
+  DeleteRow(aValue, rv);
+  return rv.ErrorCode();
+}
+
 bool
 HTMLTableSectionElement::ParseAttribute(int32_t aNamespaceID,
                                         nsIAtom* aAttribute,
                                         const nsAString& aValue,
                                         nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     /* ignore these attributes, stored simply as strings
@@ -155,17 +250,17 @@ HTMLTableSectionElement::ParseAttribute(
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static
+static 
 void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
     // height: value
     nsCSSValue* height = aData->ValueForHeight();
     if (height->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
       if (value && value->Type() == nsAttrValue::eInteger)
@@ -194,17 +289,17 @@ void MapAttributesIntoRule(const nsMappe
   nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableSectionElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
-    { &nsGkAtoms::align },
+    { &nsGkAtoms::align }, 
     { &nsGkAtoms::valign },
     { &nsGkAtoms::height },
     { nullptr }
   };
 
   static const MappedAttributeEntry* const map[] = {
     attributes,
     sCommonAttributeMap,
--- a/content/html/content/src/HTMLTableSectionElement.h
+++ b/content/html/content/src/HTMLTableSectionElement.h
@@ -2,23 +2,24 @@
 /* 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 mozilla_dom_HTMLTableSectionElement_h
 #define mozilla_dom_HTMLTableSectionElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLTableSectionElement.h"
 #include "nsContentList.h" // For ctor.
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTableSectionElement MOZ_FINAL : public nsGenericHTMLElement,
-                                          public nsIDOMHTMLElement
+                                          public nsIDOMHTMLTableSectionElement
 {
 public:
   HTMLTableSectionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
   // nsISupports
@@ -28,16 +29,19 @@ public:
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
 
+  // nsIDOMHTMLTableSectionElement
+  NS_DECL_NSIDOMHTMLTABLESECTIONELEMENT
+
   nsIHTMLCollection* Rows();
   already_AddRefed<nsGenericHTMLElement>
     InsertRow(int32_t aIndex, ErrorResult& aError);
   void DeleteRow(int32_t aValue, ErrorResult& aError);
 
   void GetAlign(nsString& aAlign)
   {
     GetHTMLAttr(nsGkAtoms::align, aAlign);
--- a/content/html/content/src/HTMLUnknownElement.cpp
+++ b/content/html/content/src/HTMLUnknownElement.cpp
@@ -1,15 +1,15 @@
 /* -*- 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/. */
 
 #include "nsDocument.h"
-#include "mozilla/dom/HTMLUnknownElement.h"
+#include "HTMLUnknownElement.h"
 #include "mozilla/dom/HTMLElementBinding.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Unknown)
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_ADDREF_INHERITED(HTMLUnknownElement, Element)
@@ -30,16 +30,19 @@ HTMLUnknownElement::WrapNode(JSContext *
       NS_ENSURE_TRUE(JS_WrapObject(aCx, prototype.address()), nullptr);
       NS_ENSURE_TRUE(JS_SetPrototype(aCx, obj, prototype), nullptr);
     }
   }
   return obj;
 }
 
 // QueryInterface implementation for HTMLUnknownElement
-NS_INTERFACE_MAP_BEGIN(HTMLUnknownElement)
+NS_INTERFACE_TABLE_HEAD(HTMLUnknownElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
+  NS_INTERFACE_TABLE_INHERITED1(HTMLUnknownElement,
+                                nsIDOMHTMLUnknownElement)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLUnknownElement)
 
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/src/HTMLUnknownElement.h
+++ b/content/html/content/src/HTMLUnknownElement.h
@@ -1,23 +1,24 @@
 /* -*- 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/. */
-#ifndef mozilla_dom_HTMLUnknownElement_h
-#define mozilla_dom_HTMLUnknownElement_h
+#ifndef HTMLUnknownElement_h___
+#define HTMLUnknownElement_h___
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIDOMHTMLUnknownElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLUnknownElement MOZ_FINAL : public nsGenericHTMLElement
-                                   , public nsIDOMHTMLElement
+                                   , public nsIDOMHTMLUnknownElement
 {
 public:
   HTMLUnknownElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
     if (NodeInfo()->Equals(nsGkAtoms::bdi)) {
       SetHasDirAuto();
     }
@@ -42,9 +43,9 @@ public:
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 };
 
 } // namespace dom
 } // namespace mozilla
 
-#endif /* mozilla_dom_HTMLUnknownElement_h */
+#endif /* HTMLUnknownElement_h___ */
--- a/content/html/content/test/test_bug389797.html
+++ b/content/html/content/test/test_bug389797.html
@@ -239,19 +239,23 @@ for (var tag of allTags) {
   is(nodeString, "[object " + classInfoString,
      "Unexpected classname for " + tagName(tag));
   is(node instanceof window[classInfoString], true,
      tagName(tag) + " not an instance of " + classInfos[tag]);
 
   if (classInfoString != 'HTMLUnknownElement') {
     is(node instanceof HTMLUnknownElement, false,
        tagName(tag) + " is an instance of HTMLUnknownElement");
+    is(node instanceof SpecialPowers.Ci.nsIDOMHTMLUnknownElement, false,
+       tagName(tag) + " is an instance of nsIDOMHTMLUnknownElement");
   } else {
     is(node instanceof HTMLUnknownElement, true,
        tagName(tag) + " is an instance of HTMLUnknownElement");
+    is(node instanceof SpecialPowers.Ci.nsIDOMHTMLUnknownElement, true,
+       tagName(tag) + " is an instance of nsIDOMHTMLUnknownElement");
   }
 
   // Check that each node QIs to all the things we expect it to QI to
   for (var iface of interfaces[tag].concat(interfacesNonClassinfo[tag])) {
     is(iface in SpecialPowers.Ci, true,
        iface + " not in Components.interfaces");
     is(node instanceof SpecialPowers.Ci[iface], true,
        tagName(tag) + " does not QI to " + iface);
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -206,47 +206,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObject)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLDocGlobalObject)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLDocGlobalObject)
 
-void
-XBL_ProtoErrorReporter(JSContext *cx,
-                       const char *message,
-                       JSErrorReport *report)
-{
-  // Make an nsIScriptError and populate it with information from
-  // this error.
-  nsCOMPtr<nsIScriptError>
-    errorObject(do_CreateInstance("@mozilla.org/scripterror;1"));
-  nsCOMPtr<nsIConsoleService>
-    consoleService(do_GetService("@mozilla.org/consoleservice;1"));
-
-  if (errorObject && consoleService) {
-    uint32_t column = report->uctokenptr - report->uclinebuf;
-
-    const PRUnichar* ucmessage =
-      static_cast<const PRUnichar*>(report->ucmessage);
-    const PRUnichar* uclinebuf =
-      static_cast<const PRUnichar*>(report->uclinebuf);
-
-    errorObject->Init
-         (ucmessage ? nsDependentString(ucmessage) : EmptyString(),
-          NS_ConvertUTF8toUTF16(report->filename),
-          uclinebuf ? nsDependentString(uclinebuf) : EmptyString(),
-          report->lineno, column, report->flags,
-          "xbl javascript"
-          );
-    consoleService->LogMessage(errorObject);
-  }
-}
-
 //----------------------------------------------------------------------
 //
 // nsIScriptGlobalObject methods
 //
 
 nsIScriptContext *
 nsXBLDocGlobalObject::GetScriptContext()
 {
@@ -275,20 +244,17 @@ nsXBLDocGlobalObject::EnsureScriptEnviro
   DebugOnly<nsresult> rv = newCtx->InitContext();
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Script Language's InitContext failed");
   newCtx->DidInitializeContext();
 
   mScriptContext = newCtx;
 
   AutoPushJSContext cx(mScriptContext->GetNativeContext());
 
-  // nsJSEnvironment set the error reporter to NS_ScriptErrorReporter so
-  // we must apparently override that with our own (although it isn't clear 
-  // why - see bug 339647)
-  JS_SetErrorReporter(cx, XBL_ProtoErrorReporter);
+  JS_SetErrorReporter(cx, xpc::SystemErrorReporter);
 
   JS::CompartmentOptions options;
   options.setZone(JS::SystemZone);
   mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass,
                                  nsJSPrincipals::get(GetPrincipal()),
                                  options);
   if (!mJSObject)
       return NS_OK;
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/898906.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script>
+
+var plug = navigator.plugins[0];
+var mime = plug[0];
+// This shouldn't leak.
+mime.expando = true;
+
+</script>
+</head>
+</html>
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -35,9 +35,10 @@ load 693811-1.html
 load 693811-2.html
 load 693811-3.html
 load 695867.html
 load 697643.html
 load 706283-1.html
 load 708405-1.html
 load 745495.html
 load 844559.html
-load 886213.html
\ No newline at end of file
+load 886213.html
+load 898906.html
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -3690,16 +3690,21 @@ OldBindingConstructorEnabled(const nsGlo
 
   // Don't expose CSSSupportsRule unless @supports processing is enabled.
   if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSSupportsRule_id) {
     if (!CSSSupportsRule::PrefEnabled()) {
       return false;
     }
   }
 
+  // Don't expose CSSFontFeatureValuesRule unless the pref is enabled
+  if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSFontFeatureValuesRule_id) {
+    return nsCSSFontFeatureValuesRule::PrefEnabled();
+  }
+
   return true;
 }
 
 // static
 nsresult
 nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
                           JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
                           bool *did_resolve)
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -15,16 +15,17 @@
 #include "nsIDocument.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMHTMLFrameElement.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMHTMLMapElement.h"
+#include "nsIDOMHTMLLegendElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMRange.h"
 #include "nsIHTMLDocument.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsLayoutUtils.h"
 #include "nsIPresShell.h"
 #include "nsIContentViewer.h"
--- a/dom/base/nsMimeTypeArray.cpp
+++ b/dom/base/nsMimeTypeArray.cpp
@@ -214,17 +214,17 @@ nsMimeTypeArray::EnsureMimeTypes()
   }
 
   mPluginMimeTypeCount = mMimeTypes.Length();
 }
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsMimeType, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsMimeType, Release)
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsMimeType)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsMimeType, mPluginElement)
 
 nsMimeType::nsMimeType(nsWeakPtr aWindow, nsPluginElement* aPluginElement,
                        uint32_t aPluginTagMimeIndex, const nsAString& aType)
   : mWindow(aWindow),
     mPluginElement(aPluginElement),
     mPluginTagMimeIndex(aPluginTagMimeIndex),
     mType(aType)
 {
--- a/dom/base/nsMimeTypeArray.h
+++ b/dom/base/nsMimeTypeArray.h
@@ -7,19 +7,19 @@
 #ifndef nsMimeTypeArray_h___
 #define nsMimeTypeArray_h___
 
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsWeakReference.h"
 #include "nsWrapperCache.h"
+#include "nsPluginArray.h"
 
 class nsPIDOMWindow;
-class nsPluginElement;
 class nsMimeType;
 
 class nsMimeTypeArray MOZ_FINAL : public nsISupports,
                                   public nsWrapperCache
 {
 public:
   nsMimeTypeArray(nsWeakPtr aWindow);
   virtual ~nsMimeTypeArray();
@@ -68,34 +68,32 @@ public:
              uint32_t aPluginTagMimeIndex, const nsAString& aMimeType);
   nsMimeType(nsWeakPtr aWindow, const nsAString& aMimeType);
   virtual ~nsMimeType();
 
   nsPIDOMWindow* GetParentObject() const;
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
-  void Invalidate()
-  {
-    mPluginElement = nullptr;
-  }
-
   const nsString& Type() const
   {
     return mType;
   }
 
   // MimeType WebIDL methods
   void GetDescription(nsString& retval) const;
   nsPluginElement *GetEnabledPlugin() const;
   void GetSuffixes(nsString& retval) const;
   void GetType(nsString& retval) const;
 
 protected:
   nsWeakPtr mWindow;
 
-  // Weak pointer to the active plugin, if any.
-  nsPluginElement *mPluginElement;
+  // Strong reference to the active plugin, if any. Note that this
+  // creates an explicit reference cycle through the plugin element's
+  // mimetype array. We rely on the cycle collector to break this
+  // cycle.
+  nsRefPtr<nsPluginElement> mPluginElement;
   uint32_t mPluginTagMimeIndex;
   nsString mType;
 };
 
 #endif /* nsMimeTypeArray_h___ */
--- a/dom/base/nsPluginArray.cpp
+++ b/dom/base/nsPluginArray.cpp
@@ -277,40 +277,26 @@ nsPluginArray::EnsurePlugins()
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPluginElement)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPluginElement)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPluginElement)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPluginElement)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-  // Invalidate before we unlink mMimeTypes
-  tmp->Invalidate();
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMimeTypes)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPluginElement)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsPluginElement)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsPluginElement, mMimeTypes)
 
 nsPluginElement::nsPluginElement(nsWeakPtr aWindow,
                                  nsPluginTag* aPluginTag)
   : mWindow(aWindow),
     mPluginTag(aPluginTag)
 {
   SetIsDOMBinding();
 }
 
-nsPluginElement::~nsPluginElement()
-{
-  Invalidate();
-}
-
 nsPIDOMWindow*
 nsPluginElement::GetParentObject() const
 {
   nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
   MOZ_ASSERT(win);
   return win;
 }
 
@@ -420,16 +406,8 @@ nsPluginElement::EnsureMimeTypes()
     return;
   }
 
   for (uint32_t i = 0; i < mPluginTag->mMimeTypes.Length(); ++i) {
     NS_ConvertUTF8toUTF16 type(mPluginTag->mMimeTypes[i]);
     mMimeTypes.AppendElement(new nsMimeType(mWindow, this, i, type));
   }
 }
-
-void
-nsPluginElement::Invalidate()
-{
-  for (uint32_t i = 0; i < mMimeTypes.Length(); ++i) {
-    mMimeTypes[i]->Invalidate();
-  }
-}
--- a/dom/base/nsPluginArray.h
+++ b/dom/base/nsPluginArray.h
@@ -69,17 +69,16 @@ private:
 class nsPluginElement MOZ_FINAL : public nsISupports,
                                   public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPluginElement)
 
   nsPluginElement(nsWeakPtr aWindow, nsPluginTag* aPluginTag);
-  virtual ~nsPluginElement();
 
   nsPIDOMWindow* GetParentObject() const;
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   nsPluginTag* PluginTag() const
   {
     return mPluginTag;
@@ -97,16 +96,15 @@ public:
   nsMimeType* NamedGetter(const nsAString& name, bool &found);
   uint32_t Length();
   void GetSupportedNames(nsTArray< nsString >& retval);
 
   nsTArray<nsRefPtr<nsMimeType> >& MimeTypes();
 
 protected:
   void EnsureMimeTypes();
-  void Invalidate();
 
   nsWeakPtr mWindow;
   nsRefPtr<nsPluginTag> mPluginTag;
   nsTArray<nsRefPtr<nsMimeType> > mMimeTypes;
 };
 
 #endif /* nsPluginArray_h___ */
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1665,18 +1665,21 @@ class CGCreateInterfaceObjectsMethod(CGA
         args = [Argument('JSContext*', 'aCx'),
                 Argument('JS::Handle<JSObject*>', 'aGlobal'),
                 Argument('JS::Heap<JSObject*>*', 'protoAndIfaceArray')]
         CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
         self.properties = properties
     def definition_body(self):
         protoChain = self.descriptor.prototypeChain
         if len(protoChain) == 1:
-            getParentProto = "aCx, JS_GetObjectPrototype(aCx, aGlobal)"
             parentProtoType = "Rooted"
+            if self.descriptor.interface.getExtendedAttribute("ArrayClass"):
+                getParentProto = "aCx, JS_GetArrayPrototype(aCx, aGlobal)"
+            else:
+                getParentProto = "aCx, JS_GetObjectPrototype(aCx, aGlobal)"
         else:
             parentProtoName = self.descriptor.prototypeChain[-2]
             getParentProto = ("%s::GetProtoObject(aCx, aGlobal)" %
                               toBindingNamespace(parentProtoName))
             parentProtoType = "Handle"
 
         parentWithInterfaceObject = self.descriptor.interface.parent
         while (parentWithInterfaceObject and
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -908,26 +908,40 @@ class IDLInterface(IDLObjectWithScope):
                     # whether the result is actually one of our existing
                     # NamedConstructors.
                     newMethod = self.parentScope.lookupIdentifier(method.identifier)
                     if newMethod == method:
                         self.namedConstructors.append(method)
                     elif not newMethod in self.namedConstructors:
                         raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface",
                                           [method.location, newMethod.location])
+            elif (identifier == "ArrayClass"):
+                if not attr.noArguments():
+                    raise WebIDLError("[ArrayClass] must take no arguments",
+                                      [attr.location])
+                if self.parent:
+                    raise WebIDLError("[ArrayClass] must not be specified on "
+                                      "an interface with inherited interfaces",
+                                      [attr.location, self.location])
             elif (identifier == "PrefControlled" or
-                  identifier == "Pref" or
                   identifier == "NeedNewResolve" or
+                  identifier == "OverrideBuiltins" or
+                  identifier == "ChromeOnly"):
+                # Known extended attributes that do not take values
+                if not attr.noArguments():
+                    raise WebIDLError("[%s] must take no arguments" % identifier,
+                                      [attr.location])
+            elif (identifier == "Pref" or
                   identifier == "JSImplementation" or
                   identifier == "HeaderFile" or
-                  identifier == "NavigatorProperty" or
-                  identifier == "OverrideBuiltins" or
-                  identifier == "ChromeOnly"):
-                # Known attributes that we don't need to do anything with here
-                pass
+                  identifier == "NavigatorProperty"):
+                # Known extended attributes that take a string value
+                if not attr.hasValue():
+                    raise WebIDLError("[%s] must have a value" % identifier,
+                                      [attr.location])
             else:
                 raise WebIDLError("Unknown extended attribute %s on interface" % identifier,
                                   [attr.location])
 
             attrlist = attr.listValue()
             self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
 
     def addImplementedInterface(self, implementedInterface):
--- a/dom/bindings/parser/tests/test_interface.py
+++ b/dom/bindings/parser/tests/test_interface.py
@@ -369,8 +369,37 @@ def WebIDLTest(parser, harness):
                 readonly attribute boolean y;
             };
         """)
         results = parser.finish()
     except:
         threw = True
     harness.ok(threw,
                "Should not allow unknown extended attributes on interfaces")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            interface B {};
+            [ArrayClass]
+            interface A : B {
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+    harness.ok(threw,
+               "Should not allow [ArrayClass] on interfaces with parents")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse("""
+            [ArrayClass]
+            interface A {
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+    harness.ok(not threw,
+               "Should allow [ArrayClass] on interfaces without parents")
--- a/dom/interfaces/base/domstubs.idl
+++ b/dom/interfaces/base/domstubs.idl
@@ -68,16 +68,17 @@ interface nsIDOMMozCSSKeyframeRule;
 interface nsIDOMCSSFontFeatureValuesRule;
 interface nsIDOMCSSStyleSheet;
 interface nsIDOMCSSStyleDeclaration;
 interface nsIDOMCounter;
 interface nsIDOMRect;
 interface nsIDOMCSSStyleRule;
 interface nsIDOMCSSStyleRuleCollection;
 interface nsIDOMHTMLTableCaptionElement;
+interface nsIDOMHTMLTableSectionElement;
 
 // Range
 interface nsIDOMRange;
 
 // Crypto
 interface nsIDOMCRMFObject;
 interface nsIDOMCrypto;
 interface nsIDOMPkcs11;
--- a/dom/interfaces/html/moz.build
+++ b/dom/interfaces/html/moz.build
@@ -11,55 +11,71 @@ XPIDL_SOURCES += [
     'nsIDOMHTMLAudioElement.idl',
     'nsIDOMHTMLBRElement.idl',
     'nsIDOMHTMLBaseElement.idl',
     'nsIDOMHTMLBodyElement.idl',
     'nsIDOMHTMLButtonElement.idl',
     'nsIDOMHTMLByteRanges.idl',
     'nsIDOMHTMLCanvasElement.idl',
     'nsIDOMHTMLCollection.idl',
+    'nsIDOMHTMLDListElement.idl',
+    'nsIDOMHTMLDataListElement.idl',
     'nsIDOMHTMLDirectoryElement.idl',
     'nsIDOMHTMLDivElement.idl',
     'nsIDOMHTMLDocument.idl',
     'nsIDOMHTMLElement.idl',
     'nsIDOMHTMLEmbedElement.idl',
     'nsIDOMHTMLFieldSetElement.idl',
+    'nsIDOMHTMLFontElement.idl',
     'nsIDOMHTMLFormElement.idl',
     'nsIDOMHTMLFrameElement.idl',
     'nsIDOMHTMLFrameSetElement.idl',
     'nsIDOMHTMLHRElement.idl',
     'nsIDOMHTMLHeadElement.idl',
+    'nsIDOMHTMLHeadingElement.idl',
     'nsIDOMHTMLHtmlElement.idl',
     'nsIDOMHTMLIFrameElement.idl',
     'nsIDOMHTMLImageElement.idl',
     'nsIDOMHTMLInputElement.idl',
     'nsIDOMHTMLLIElement.idl',
+    'nsIDOMHTMLLabelElement.idl',
+    'nsIDOMHTMLLegendElement.idl',
     'nsIDOMHTMLLinkElement.idl',
     'nsIDOMHTMLMapElement.idl',
     'nsIDOMHTMLMediaElement.idl',
     'nsIDOMHTMLMenuElement.idl',
     'nsIDOMHTMLMenuItemElement.idl',
     'nsIDOMHTMLMetaElement.idl',
+    'nsIDOMHTMLMeterElement.idl',
+    'nsIDOMHTMLModElement.idl',
     'nsIDOMHTMLOListElement.idl',
     'nsIDOMHTMLObjectElement.idl',
     'nsIDOMHTMLOptGroupElement.idl',
     'nsIDOMHTMLOptionElement.idl',
     'nsIDOMHTMLOptionsCollection.idl',
+    'nsIDOMHTMLOutputElement.idl',
     'nsIDOMHTMLParagraphElement.idl',
+    'nsIDOMHTMLParamElement.idl',
     'nsIDOMHTMLPreElement.idl',
+    'nsIDOMHTMLProgressElement.idl',
     'nsIDOMHTMLQuoteElement.idl',
     'nsIDOMHTMLScriptElement.idl',
     'nsIDOMHTMLSelectElement.idl',
     'nsIDOMHTMLSourceElement.idl',
     'nsIDOMHTMLStyleElement.idl',
     'nsIDOMHTMLTableCaptionElem.idl',
+    'nsIDOMHTMLTableCellElement.idl',
+    'nsIDOMHTMLTableColElement.idl',
     'nsIDOMHTMLTableElement.idl',
+    'nsIDOMHTMLTableRowElement.idl',
+    'nsIDOMHTMLTableSectionElement.idl',
     'nsIDOMHTMLTextAreaElement.idl',
     'nsIDOMHTMLTitleElement.idl',
     'nsIDOMHTMLUListElement.idl',
+    'nsIDOMHTMLUnknownElement.idl',
     'nsIDOMHTMLVideoElement.idl',
     'nsIDOMMediaError.idl',
     'nsIDOMMozBrowserFrame.idl',
     'nsIDOMTimeRanges.idl',
     'nsIDOMValidityState.idl',
     'nsIMozBrowserFrame.idl',
 ]
 
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLDListElement.idl
@@ -0,0 +1,23 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLDListElement interface is the interface to a [X]HTML
+ * dl element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(edd9338b-f0d5-4825-97d6-6a49862309cc)]
+interface nsIDOMHTMLDListElement : nsIDOMHTMLElement
+{
+           attribute boolean          compact;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLDataListElement.idl
@@ -0,0 +1,25 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLDataListElement interface is the interface to a HTML
+ * <datalist> element.
+ *
+ * For more information on this interface, please see
+ * http://www.whatwg.org/specs/web-apps/current-work/#the-datalist-element
+ *
+ * @status UNDER_DEVELOPMENT
+ */
+
+interface nsIDOMHTMLCollection;
+
+[scriptable, uuid(528e6a6b-f957-42e1-8d1b-eeeb2fd0b128)]
+interface nsIDOMHTMLDataListElement : nsIDOMHTMLElement
+{
+  readonly attribute nsIDOMHTMLCollection options;
+};
+
--- a/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLDirectoryElement.idl
@@ -11,13 +11,13 @@
  *
  * This interface is trying to follow the DOM Level 2 HTML specification:
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
-// Exists so that | element instanceof Ci.nsIDOMHTMLDirectoryElement | works.
 [scriptable, uuid(cf50373e-e004-4cec-bc65-be9250d9e4c8)]
 interface nsIDOMHTMLDirectoryElement : nsIDOMHTMLElement
 {
+           attribute boolean          compact;
 };
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLFontElement.idl
@@ -0,0 +1,25 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLFontElement interface is the interface to a [X]HTML
+ * font element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(e4d86aad-f245-4901-877e-0ae233c5fd37)]
+interface nsIDOMHTMLFontElement : nsIDOMHTMLElement
+{
+           attribute DOMString        color;
+           attribute DOMString        face;
+           attribute DOMString        size;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLHeadingElement.idl
@@ -0,0 +1,23 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLHeadingElement interface is the interface to a
+ * [X]HTML h1, h2, h3, ... element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(e601aadf-e9e7-4605-a6f9-2cd2006723de)]
+interface nsIDOMHTMLHeadingElement : nsIDOMHTMLElement
+{
+           attribute DOMString        align;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLLabelElement.idl
@@ -0,0 +1,25 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLLabelElement interface is the interface to a [X]HTML
+ * label element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(cbffa708-f51e-4c74-9644-19f9d417aac5)]
+interface nsIDOMHTMLLabelElement : nsIDOMHTMLElement
+{
+  readonly attribute nsIDOMHTMLFormElement form;
+           attribute DOMString             htmlFor;
+  readonly attribute nsIDOMHTMLElement     control;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLLegendElement.idl
@@ -0,0 +1,24 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLLegendElement interface is the interface to a [X]HTML
+ * legend element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(2e4567be-3d91-4df8-bdf9-f3bd96a6cd06)]
+interface nsIDOMHTMLLegendElement : nsIDOMHTMLElement
+{
+  readonly attribute nsIDOMHTMLFormElement form;
+           attribute DOMString             align;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLMeterElement.idl
@@ -0,0 +1,30 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLMeterElement interface is the interface to a HTML
+ * <meter> element.
+ *
+ * For more information on this interface, please see
+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-meter-element
+ */
+
+[scriptable, uuid(6b1fc313-a7c1-4064-ba24-b72e099b05fa)]
+interface nsIDOMHTMLMeterElement : nsIDOMHTMLElement
+{
+           attribute double value;
+           attribute double min;
+           attribute double max;
+           attribute double low;
+           attribute double high;
+           attribute double optimum;
+
+  /**
+   * The labels attribute will be done with bug 556743.
+   */
+  //readonly attribute NodeList labels;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLModElement.idl
@@ -0,0 +1,24 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLModElement interface is the interface to a [X]HTML
+ * ins and del element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(8a1bdf64-19f3-401b-aaea-8c6a5ef1c66f)]
+interface nsIDOMHTMLModElement : nsIDOMHTMLElement
+{
+           attribute DOMString        cite;
+           attribute DOMString        dateTime;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLOutputElement.idl
@@ -0,0 +1,43 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLOutputElement interface is the interface to a HTML
+ * <output> element.
+ *
+ * For more information on this interface, please see
+ * http://www.whatwg.org/specs/web-apps/current-work/#the-output-element
+ *
+ * @status UNDER_DEVELOPMENT
+ */
+
+interface nsIDOMValidityState;
+
+[scriptable, uuid(c4bff576-90b5-44b0-8278-bf4e3010b09a)]
+interface nsIDOMHTMLOutputElement : nsIDOMHTMLElement
+{
+  // DOMSettableTokenList
+  readonly attribute nsISupports                htmlFor;
+  readonly attribute nsIDOMHTMLFormElement      form;
+           attribute DOMString                  name;
+
+  readonly attribute DOMString                  type;
+           attribute DOMString                  defaultValue;
+           attribute DOMString                  value;
+
+  readonly attribute boolean                    willValidate;
+  readonly attribute nsIDOMValidityState        validity;
+  readonly attribute DOMString                  validationMessage;
+  boolean  checkValidity();
+  void     setCustomValidity(in DOMString error);
+
+  /**
+   * The labels IDL attribute will be added with bug 556743.
+   */
+  //readonly attribute nsIDOMNodeList             labels;
+};
+
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLParamElement.idl
@@ -0,0 +1,26 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLParamElement interface is the interface to a [X]HTML
+ * param element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(f85e1b05-6dc4-442d-bea8-7cf551f9bc9f)]
+interface nsIDOMHTMLParamElement : nsIDOMHTMLElement
+{
+           attribute DOMString        name;
+           attribute DOMString        type;
+           attribute DOMString        value;
+           attribute DOMString        valueType;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLProgressElement.idl
@@ -0,0 +1,29 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLProgressElement interface is the interface to a HTML
+ * <progress> element.
+ *
+ * For more information on this interface, please see
+ * http://www.whatwg.org/specs/web-apps/current-work/#the-progress-element
+ *
+ * @status UNDER_DEVELOPMENT
+ */
+
+[scriptable, uuid(4b4bec16-c65f-4a08-97d1-dff624efdca4)]
+interface nsIDOMHTMLProgressElement : nsIDOMHTMLElement
+{
+           attribute double value;
+           attribute double max;
+  readonly attribute double position;
+  /**
+   * The labels attribute will be done with bug 567740.
+   */
+  //readonly attribute NodeList labels;
+};
+
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLTableCellElement.idl
@@ -0,0 +1,37 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLTableCellElement interface is the interface to a
+ * [X]HTML td element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(1fb22137-c231-4eae-9ca4-557bb0852d89)]
+interface nsIDOMHTMLTableCellElement : nsIDOMHTMLElement
+{
+  readonly attribute long             cellIndex;
+           attribute DOMString        abbr;
+           attribute DOMString        align;
+           attribute DOMString        axis;
+           attribute DOMString        bgColor;
+           attribute DOMString        ch;
+           attribute DOMString        chOff;
+           attribute long             colSpan;
+           attribute DOMString        headers;
+           attribute DOMString        height;
+           attribute boolean          noWrap;
+           attribute long             rowSpan;
+           attribute DOMString        scope;
+           attribute DOMString        vAlign;
+           attribute DOMString        width;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLTableColElement.idl
@@ -0,0 +1,28 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLTableColElement interface is the interface to a
+ * [X]HTML col element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(cd5a5a33-7101-4d32-987c-337c004fce1a)]
+interface nsIDOMHTMLTableColElement : nsIDOMHTMLElement
+{
+           attribute DOMString        align;
+           attribute DOMString        ch;
+           attribute DOMString        chOff;
+           attribute long             span;
+           attribute DOMString        vAlign;
+           attribute DOMString        width;
+};
--- a/dom/interfaces/html/nsIDOMHTMLTableElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLTableElement.idl
@@ -14,9 +14,44 @@
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
 [scriptable, uuid(1a7bf1f1-5d6c-4200-9ceb-455874322315)]
 interface nsIDOMHTMLTableElement : nsIDOMHTMLElement
 {
+  // Modified in DOM Level 2:
+           attribute nsIDOMHTMLTableCaptionElement caption;
+                                             // raises(DOMException) on setting
+
+  // Modified in DOM Level 2:
+           attribute nsIDOMHTMLTableSectionElement tHead;
+                                             // raises(DOMException) on setting
+
+  // Modified in DOM Level 2:
+           attribute nsIDOMHTMLTableSectionElement tFoot;
+                                             // raises(DOMException) on setting
+
+  readonly attribute nsIDOMHTMLCollection          rows;
+  readonly attribute nsIDOMHTMLCollection          tBodies;
+           attribute DOMString                     align;
+           attribute DOMString                     bgColor;
+           attribute DOMString                     border;
+           attribute DOMString                     cellPadding;
+           attribute DOMString                     cellSpacing;
+           attribute DOMString                     frame;
+           attribute DOMString                     rules;
+           attribute DOMString                     summary;
+           attribute DOMString                     width;
+  nsIDOMHTMLElement         createTHead();
+  void                      deleteTHead();
+  nsIDOMHTMLElement         createTFoot();
+  void                      deleteTFoot();
+  nsIDOMHTMLElement         createCaption();
+  void                      deleteCaption();
+  // Modified in DOM Level 2:
+  nsIDOMHTMLElement         insertRow(in long index)
+                                             raises(DOMException);
+  // Modified in DOM Level 2:
+  void                      deleteRow(in long index)
+                                             raises(DOMException);
 };
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLTableRowElement.idl
@@ -0,0 +1,39 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLTableRowElement interface is the interface to a
+ * [X]HTML tr element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, uuid(02094366-0d3d-47e3-949c-89113a9bcc15)]
+interface nsIDOMHTMLTableRowElement : nsIDOMHTMLElement
+{
+  // Modified in DOM Level 2:
+  readonly attribute long                 rowIndex;
+  // Modified in DOM Level 2:
+  readonly attribute long                 sectionRowIndex;
+  // Modified in DOM Level 2:
+  readonly attribute nsIDOMHTMLCollection cells;
+           attribute DOMString            align;
+           attribute DOMString            bgColor;
+           attribute DOMString            ch;
+           attribute DOMString            chOff;
+           attribute DOMString            vAlign;
+  // Modified in DOM Level 2:
+  nsIDOMHTMLElement         insertCell(in long index)
+                                               raises(DOMException);
+  // Modified in DOM Level 2:
+  void                      deleteCell(in long index)
+                                               raises(DOMException);
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLTableSectionElement.idl
@@ -0,0 +1,33 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLTableSectionElement interface is the interface to a
+ * [X]HTML thead, tbody, and tfoot element.
+ *
+ * This interface is trying to follow the DOM Level 2 HTML specification:
+ * http://www.w3.org/TR/DOM-Level-2-HTML/
+ *
+ * with changes from the work-in-progress WHATWG HTML specification:
+ * http://www.whatwg.org/specs/web-apps/current-work/
+ */
+
+[scriptable, builtinclass, uuid(7b91cf4c-5194-4122-bc29-7bbd18ba0020)]
+interface nsIDOMHTMLTableSectionElement : nsIDOMHTMLElement
+{
+           attribute DOMString            align;
+           attribute DOMString            ch;
+           attribute DOMString            chOff;
+           attribute DOMString            vAlign;
+  readonly attribute nsIDOMHTMLCollection rows;
+  // Modified in DOM Level 2:
+  nsIDOMHTMLElement         insertRow(in long index)
+                                               raises(DOMException);
+  // Modified in DOM Level 2:
+  void                      deleteRow(in long index)
+                                               raises(DOMException);
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/html/nsIDOMHTMLUnknownElement.idl
@@ -0,0 +1,17 @@
+/* -*- Mode: IDL; 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/. */
+
+#include "nsIDOMHTMLElement.idl"
+
+/**
+ * The nsIDOMHTMLUnknownElement interface is the interface to an unknown HTML
+ * element.
+ *
+ * @see <http://www.whatwg.org/html/#htmlunknownelement>
+ */
+[scriptable, uuid(aa044a2d-4e9b-4fc5-8ad2-666da9062b36)]
+interface nsIDOMHTMLUnknownElement : nsIDOMHTMLElement
+{
+};
--- a/dom/webidl/HTMLHeadingElement.webidl
+++ b/dom/webidl/HTMLHeadingElement.webidl
@@ -12,11 +12,10 @@
  */
 
 // http://www.whatwg.org/specs/web-apps/current-work/#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements
 interface HTMLHeadingElement : HTMLElement {
 };
 
 // http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
 partial interface HTMLHeadingElement {
-           [SetterThrows]
            attribute DOMString align;
 };
--- a/dom/webidl/HTMLLabelElement.webidl
+++ b/dom/webidl/HTMLLabelElement.webidl
@@ -8,12 +8,11 @@
  *
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
 interface HTMLLabelElement : HTMLElement {
   readonly attribute HTMLFormElement? form;
-           [SetterThrows]
            attribute DOMString htmlFor;
   readonly attribute HTMLElement? control;
 };
--- a/dom/webidl/HTMLLegendElement.webidl
+++ b/dom/webidl/HTMLLegendElement.webidl
@@ -14,11 +14,10 @@
 
 // http://www.whatwg.org/specs/web-apps/current-work/#the-legend-element
 interface HTMLLegendElement : HTMLElement {
   readonly attribute HTMLFormElement? form;
 };
 
 // http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
 partial interface HTMLLegendElement {
-           [SetterThrows]
            attribute DOMString align;
 };
--- a/dom/webidl/HTMLTableColElement.webidl
+++ b/dom/webidl/HTMLTableColElement.webidl
@@ -7,24 +7,18 @@
  * http://www.whatwg.org/specs/web-apps/current-work/
  *
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
 interface HTMLTableColElement : HTMLElement {
-           [SetterThrows]
            attribute unsigned long span;
 };
 
 partial interface HTMLTableColElement {
-           [SetterThrows]
            attribute DOMString align;
-           [SetterThrows]
            attribute DOMString ch;
-           [SetterThrows]
            attribute DOMString chOff;
-           [SetterThrows]
            attribute DOMString vAlign;
-           [SetterThrows]
            attribute DOMString width;
 };
--- a/gfx/layers/CopyableCanvasLayer.cpp
+++ b/gfx/layers/CopyableCanvasLayer.cpp
@@ -69,33 +69,38 @@ CopyableCanvasLayer::UpdateSurface(gfxAS
   if (!mGLContext && aDestSurface) {
     nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface);
     tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
     CopyableCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f, aMaskLayer);
     return;
   }
 
   if (mGLContext) {
+    if (aDestSurface && aDestSurface->GetType() != gfxASurface::SurfaceTypeImage) {
+      MOZ_ASSERT(false, "Destination surface must be ImageSurface type.");
+      return;
+    }
+
     nsRefPtr<gfxImageSurface> readSurf;
     nsRefPtr<gfxImageSurface> resultSurf;
 
     SharedSurface* sharedSurf = mGLContext->RequestFrame();
     if (!sharedSurf) {
       NS_WARNING("Null frame received.");
       return;
     }
 
     gfxIntSize readSize(sharedSurf->Size());
     gfxImageFormat format = (GetContentFlags() & CONTENT_OPAQUE)
                             ? gfxASurface::ImageFormatRGB24
                             : gfxASurface::ImageFormatARGB32;
 
-    bool needsTempSurface = !aDestSurface ||
-                            !(resultSurf = aDestSurface->GetAsImageSurface());
-    if (needsTempSurface) {
+    if (aDestSurface) {
+      resultSurf = static_cast<gfxImageSurface*>(aDestSurface);
+    } else {
       resultSurf = GetTempSurface(readSize, format);
     }
     MOZ_ASSERT(resultSurf);
     if (resultSurf->CairoStatus() != 0) {
       MOZ_ASSERT(false, "Bad resultSurf->CairoStatus().");
       return;
     }
 
@@ -146,17 +151,17 @@ CopyableCanvasLayer::UpdateSurface(gfxAS
       readSurf->Flush();
       nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf);
       ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
       ctx->SetSource(readSurf);
       ctx->Paint();
     }
 
     // stick our surface into mSurface, so that the Paint() path is the same
-    if (needsTempSurface) {
+    if (!aDestSurface) {
       mSurface = resultSurf;
     }
   }
 }
 
 void
 CopyableCanvasLayer::PaintWithOpacity(gfxContext* aContext,
                                       float aOpacity,
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -61,17 +61,17 @@ CanvasClient2D::Update(gfx::IntSize aSiz
   }
 
   bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
   gfxASurface::gfxContentType contentType = isOpaque
                                               ? gfxASurface::CONTENT_COLOR
                                               : gfxASurface::CONTENT_COLOR_ALPHA;
   mDeprecatedTextureClient->EnsureAllocated(aSize, contentType);
 
-  gfxASurface* surface = mDeprecatedTextureClient->LockSurface();
+  gfxASurface* surface = mDeprecatedTextureClient->LockImageSurface();
   aLayer->UpdateSurface(surface);
   mDeprecatedTextureClient->Unlock();
 }
 
 void
 CanvasClientWebGL::Updated()
 {
   mForwarder->UpdateTextureNoSwap(this, 1, mDeprecatedTextureClient->GetDescriptor());
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -242,16 +242,21 @@ nsBMPDecoder::WriteInternal(const char* 
         // BMPs with negative width are invalid
         // Reject extremely wide images to keep the math sane
         const int32_t k64KWidth = 0x0000FFFF;
         if (mBIH.width < 0 || mBIH.width > k64KWidth) {
             PostDataError();
             return;
         }
 
+        if (mBIH.height == INT_MIN) {
+            PostDataError();
+            return;
+        }
+
         uint32_t real_height = GetHeight();
 
         // Post our size to the superclass
         PostSize(mBIH.width, real_height);
         if (HasError()) {
           // Setting the size led to an error.
           return;
         }
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d9a00161072ae6d3378dcaeea12079c873d4012d
GIT binary patch
literal 60
kc${<cwPAn&Ga%MrfP)4`1_>~O4Ty!fAs7Z~8JdA40AFzf0{{R3
--- a/image/test/mochitest/Makefile.in
+++ b/image/test/mochitest/Makefile.in
@@ -65,16 +65,18 @@ MOCHITEST_FILES =   imgutils.js \
                 bug767779.sjs \
                 animated-gif_trailing-garbage.gif \
 		test_error_events.html \
 		error-early.png \
 		test_drawDiscardedImage.html \
 		short_header.gif \
 		test_short_gif_header.html \
                 test_ImageContentLoaded.html \
+                INT32_MIN.bmp \
+                test_bug865919.html \
                 $(NULL)
 
 # Tests disabled due to intermittent orange
 # test_bug435296.html disabled - See bug 578591
 # test_bug478398.html disabled - See bug 579139
 
 MOCHITEST_CHROME_FILES = imgutils.js \
                 animationPolling.js \
new file mode 100644
--- /dev/null
+++ b/image/test/mochitest/test_bug865919.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=865919
+-->
+<head>
+  <meta charset="UTF-8">
+  <title>Test for Bug 865919</title>
+  <script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script type="text/javascript">
+"use strict";
+
+/* Test for Bug 865919:
+ *  BMP with height of INT32_MIN should fail to decode.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+var req = new XMLHttpRequest();
+req.onload  = function() { CallbackAssert(true,  'Request for file succeeded.'); };
+req.onerror = function() { CallbackAssert(false, 'Request for file failed! Failed to test non-existent file.'); };
+req.open('GET', 'INT32_MIN.bmp');
+req.send(null);
+
+var outstandingCallbacks = 2;
+
+function CallbackAssert(assertVal, failText) {
+  ok(assertVal, failText);
+  
+  outstandingCallbacks--;
+  ok(outstandingCallbacks >= 0, '`outstandingCallbacks` should be non-negative.');
+  if (outstandingCallbacks)
+    return;
+
+  // No outstanding callbacks remain, so we're done.
+  SimpleTest.finish();
+}
+
+</script>
+
+<div id='content'>
+  <img src='INT32_MIN.bmp'
+       onerror='CallbackAssert(true, "Got expected onerror for INT32_MIN.bmp")'
+       onload='CallbackAssert(false, "Got unexpected onload for INT32_MIN.bmp")'>
+</div>
+
+</body>
+</html>
+
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -742,24 +742,28 @@ EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselis
 EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
 EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist -- $(LD)
 EXPAND_MKSHLIB_ARGS = --uselist
 ifdef SYMBOL_ORDER
 EXPAND_MKSHLIB_ARGS += --symbol-order $(SYMBOL_ORDER)
 endif
 EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) $(EXPAND_MKSHLIB_ARGS) -- $(MKSHLIB)
 
-ifdef STDCXX_COMPAT
+ifneq (,$(MOZ_LIBSTDCXX_TARGET_VERSION)$(MOZ_LIBSTDCXX_HOST_VERSION))
 ifneq ($(OS_ARCH),Darwin)
 CHECK_STDCXX = objdump -p $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' > /dev/null && echo "TEST-UNEXPECTED-FAIL | | We don't want these libstdc++ symbols to be used:" && objdump -T $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && exit 1 || exit 0
 endif
 
+ifdef MOZ_LIBSTDCXX_TARGET_VERSION
 EXTRA_LIBS += $(call EXPAND_LIBNAME_PATH,stdc++compat,$(DEPTH)/build/unix/stdc++compat)
+endif
+ifdef MOZ_LIBSTDCXX_HOST_VERSION
 HOST_EXTRA_LIBS += $(call EXPAND_LIBNAME_PATH,host_stdc++compat,$(DEPTH)/build/unix/stdc++compat)
 endif
+endif
 
 # autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
 # this file
 OBJ_SUFFIX := $(_OBJ_SUFFIX)
 
 # PGO builds with GCC build objects with instrumentation in a first pass,
 # then objects optimized, without instrumentation, in a second pass. If
 # we overwrite the ojects from the first pass with those from the second,
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -2408,18 +2408,16 @@ AutoFlushInhibitor::~AutoFlushInhibitor(
         return;
     JS_ASSERT(ic_->flusher() == NULL);
     // Ensure any future modifications are recorded
     ic_->setFlusher(afc);
     if (afc)
         IonSpewCont(IonSpew_CacheFlush, "{");
 }
 
-int js::ion::LabelBase::id_count = 0;
-
 void
 ion::PurgeCaches(JSScript *script, Zone *zone)
 {
     if (script->hasIonScript())
         script->ionScript()->purgeCaches(zone);
 
     if (script->hasParallelIonScript())
         script->parallelIonScript()->purgeCaches(zone);
--- a/js/src/ion/LIR-Common.h
+++ b/js/src/ion/LIR-Common.h
@@ -4398,20 +4398,16 @@ class LGuardThreadLocalObject : public L
     LIR_HEADER(GuardThreadLocalObject);
 
     LGuardThreadLocalObject(const LAllocation &slice, const LAllocation &object, const LDefinition &temp1) {
         setOperand(0, slice);
         setOperand(1, object);
         setTemp(0, temp1);
     }
 
-    bool isCall() const {
-        return true;
-    }
-
     const LAllocation *forkJoinSlice() {
         return getOperand(0);
     }
 
     const LAllocation *object() {
         return getOperand(1);
     }
 
@@ -4847,17 +4843,17 @@ class LAsmJSCall MOZ_FINAL : public LIns
     {}
 
     MAsmJSCall *mir() const {
         return mir_->toAsmJSCall();
     }
 
     bool isCall() const {
         return true;
-    };
+    }
 
     // LInstruction interface
     size_t numDefs() const {
         return def_.isBogusTemp() ? 0 : 1;
     }
     LDefinition *getDef(size_t index) {
         JS_ASSERT(numDefs() == 1);
         JS_ASSERT(index == 0);
--- a/js/src/ion/LIR.h
+++ b/js/src/ion/LIR.h
@@ -56,23 +56,24 @@ static const uint32_t PAYLOAD_INDEX = 1;
 #endif
 
 // Represents storage for an operand. For constants, the pointer is tagged
 // with a single bit, and the untagged pointer is a pointer to a Value.
 class LAllocation : public TempObject
 {
     uintptr_t bits_;
 
-  protected:
     static const uintptr_t TAG_BIT = 1;
     static const uintptr_t TAG_SHIFT = 0;
     static const uintptr_t TAG_MASK = 1 << TAG_SHIFT;
     static const uintptr_t KIND_BITS = 4;
     static const uintptr_t KIND_SHIFT = TAG_SHIFT + TAG_BIT;
     static const uintptr_t KIND_MASK = (1 << KIND_BITS) - 1;
+
+  protected:
     static const uintptr_t DATA_BITS = (sizeof(uint32_t) * 8) - KIND_BITS - TAG_BIT;
     static const uintptr_t DATA_SHIFT = KIND_SHIFT + KIND_BITS;
     static const uintptr_t DATA_MASK = (1 << DATA_BITS) - 1;
 
   public:
     enum Kind {
         USE,            // Use of a virtual register, with physical allocation policy.
         CONSTANT_VALUE, // Constant js::Value.
--- a/js/src/ion/LiveRangeAllocator.cpp
+++ b/js/src/ion/LiveRangeAllocator.cpp
@@ -397,31 +397,31 @@ IsInputReused(LInstruction *ins, LUse *u
  */
 template <typename VREG>
 bool
 LiveRangeAllocator<VREG>::init()
 {
     if (!RegisterAllocator::init())
         return false;
 
-    liveIn = lir->mir()->allocate<BitSet*>(graph.numBlockIds());
+    liveIn = mir->allocate<BitSet*>(graph.numBlockIds());
     if (!liveIn)
         return false;
 
     // Initialize fixed intervals.
     for (size_t i = 0; i < AnyRegister::Total; i++) {
         AnyRegister reg = AnyRegister::FromCode(i);
         LiveInterval *interval = new LiveInterval(0);
         interval->setAllocation(LAllocation(reg));
         fixedIntervals[i] = interval;
     }
 
     fixedIntervalsUnion = new LiveInterval(0);
 
-    if (!vregs.init(lir->mir(), graph.numVirtualRegisters()))
+    if (!vregs.init(mir, graph.numVirtualRegisters()))
         return false;
 
     // Build virtual register objects
     for (size_t i = 0; i < graph.numBlocks(); i++) {
         if (mir->shouldCancel("LSRA create data structures (main loop)"))
             return false;
 
         LBlock *block = graph.getBlock(i);
--- a/js/src/ion/LiveRangeAllocator.h
+++ b/js/src/ion/LiveRangeAllocator.h
@@ -534,28 +534,26 @@ class LiveRangeAllocator : public Regist
     // registers, and shifting the boundaries of live ranges by small amounts.
     // This exists because different allocators handle live ranges differently;
     // ideally, they would all treat live ranges in the same way.
     bool forLSRA;
 
     // Allocation state
     StackSlotAllocator stackSlotAllocator;
 
-  public:
     LiveRangeAllocator(MIRGenerator *mir, LIRGenerator *lir, LIRGraph &graph, bool forLSRA)
       : RegisterAllocator(mir, lir, graph),
         liveIn(NULL),
         fixedIntervalsUnion(NULL),
         forLSRA(forLSRA)
     {
     }
 
     bool buildLivenessInfo();
 
-  protected:
     bool init();
 
     bool addFixedRangeAtHead(AnyRegister reg, CodePosition from, CodePosition to) {
         if (!fixedIntervals[reg.code()]->addRangeAtHead(from, to))
             return false;
         return fixedIntervalsUnion->addRangeAtHead(from, to);
     }
 
--- a/js/src/ion/MIR.cpp
+++ b/js/src/ion/MIR.cpp
@@ -154,17 +154,17 @@ MDefinition::valueHash() const
     for (size_t i = 0, e = numOperands(); i < e; i++) {
         uint32_t valueNumber = getOperand(i)->valueNumber();
         out = valueNumber + (out << 6) + (out << 16) - out;
     }
     return out;
 }
 
 bool
-MDefinition::congruentIfOperandsEqual(MDefinition * const &ins) const
+MDefinition::congruentIfOperandsEqual(MDefinition *ins) const
 {
     if (numOperands() != ins->numOperands())
         return false;
 
     if (op() != ins->op())
         return false;
 
     if (type() != ins->type())
@@ -388,17 +388,17 @@ MConstant::MConstant(const js::Value &vp
 HashNumber
 MConstant::valueHash() const
 {
     // This disregards some state, since values are 64 bits. But for a hash,
     // it's completely acceptable.
     return (HashNumber)JSVAL_TO_IMPL(value_).asBits;
 }
 bool
-MConstant::congruentTo(MDefinition * const &ins) const
+MConstant::congruentTo(MDefinition *ins) const
 {
     if (!ins->isConstant())
         return false;
     return ins->toConstant()->value() == value();
 }
 
 void
 MConstant::printOpcode(FILE *fp) const
@@ -489,17 +489,17 @@ MParameter::printOpcode(FILE *fp) const
 
 HashNumber
 MParameter::valueHash() const
 {
     return index_; // Why not?
 }
 
 bool
-MParameter::congruentTo(MDefinition * const &ins) const
+MParameter::congruentTo(MDefinition *ins) const
 {
     if (!ins->isParameter())
         return false;
 
     return ins->toParameter()->index() == index_;
 }
 
 MCall *
@@ -642,17 +642,17 @@ MPhi::foldsTo(bool useValueNumbers)
         if (!EqualValues(false, getOperand(i), first))
             return this;
     }
 
     return first;
 }
 
 bool
-MPhi::congruentTo(MDefinition *const &ins) const
+MPhi::congruentTo(MDefinition *ins) const
 {
     if (!ins->isPhi())
         return false;
     // Since we do not know which predecessor we are merging from, we must
     // assume that phi instructions in different blocks are not equal.
     // (Bug 674656)
     if (ins->block()->id() != block()->id())
         return false;
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -363,20 +363,20 @@ class MDefinition : public MNode
     Range *range() const {
         return range_;
     }
     void setRange(Range *range) {
         range_ = range;
     }
 
     virtual HashNumber valueHash() const;
-    virtual bool congruentTo(MDefinition* const &ins) const {
+    virtual bool congruentTo(MDefinition *ins) const {
         return false;
     }
-    bool congruentIfOperandsEqual(MDefinition * const &ins) const;
+    bool congruentIfOperandsEqual(MDefinition *ins) const;
     virtual MDefinition *foldsTo(bool useValueNumbers);
     virtual void analyzeEdgeCasesForward();
     virtual void analyzeEdgeCasesBackward();
 
     virtual bool truncate();
     virtual bool isOperandTruncated(size_t index) const;
 
     bool earlyAbortCheck();
@@ -707,17 +707,17 @@ class MBinaryInstruction : public MAryIn
         return op() ^ lhs->valueNumber() ^ rhs->valueNumber();
     }
     void swapOperands() {
         MDefinition *temp = getOperand(0);
         replaceOperand(0, getOperand(1));
         replaceOperand(1, temp);
     }
 
-    bool congruentTo(MDefinition *const &ins) const
+    bool congruentTo(MDefinition *ins) const
     {
         if (op() != ins->op())
             return false;
 
         if (type() != ins->type())
             return false;
 
         if (isEffectful() || ins->isEffectful())
@@ -767,17 +767,17 @@ class MTernaryInstruction : public MAryI
     {
         MDefinition *first = getOperand(0);
         MDefinition *second = getOperand(1);
         MDefinition *third = getOperand(2);
 
         return op() ^ first->valueNumber() ^ second->valueNumber() ^ third->valueNumber();
     }
 
-    bool congruentTo(MDefinition *const &ins) const
+    bool congruentTo(MDefinition *ins) const
     {
         if (op() != ins->op())
             return false;
 
         if (type() != ins->type())
             return false;
 
         if (isEffectful() || ins->isEffectful())
@@ -816,17 +816,17 @@ class MQuaternaryInstruction : public MA
         MDefinition *second = getOperand(1);
         MDefinition *third = getOperand(2);
         MDefinition *fourth = getOperand(3);
 
         return op() ^ first->valueNumber() ^ second->valueNumber() ^
                       third->valueNumber() ^ fourth->valueNumber();
     }
 
-    bool congruentTo(MDefinition *const &ins) const
+    bool congruentTo(MDefinition *ins) const
     {
         if (op() != ins->op())
             return false;
 
         if (type() != ins->type())
             return false;
 
         if (isEffectful() || ins->isEffectful())
@@ -930,17 +930,17 @@ class MConstant : public MNullaryInstruc
     }
     const js::Value *vp() const {
         return &value_;
     }
 
     void printOpcode(FILE *fp) const;
 
     HashNumber valueHash() const;
-    bool congruentTo(MDefinition * const &ins) const;
+    bool congruentTo(MDefinition *ins) const;
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 
     void computeRange();
     bool truncate();
 };
@@ -964,32 +964,32 @@ class MParameter : public MNullaryInstru
     static MParameter *New(int32_t index, types::StackTypeSet *types);
 
     int32_t index() const {
         return index_;
     }
     void printOpcode(FILE *fp) const;
 
     HashNumber valueHash() const;
-    bool congruentTo(MDefinition * const &ins) const;
+    bool congruentTo(MDefinition *ins) const;
 };
 
 class MCallee : public MNullaryInstruction
 {
   public:
     MCallee()
     {
         setResultType(MIRType_Object);
         setMovable();
     }
 
   public:
     INSTRUCTION_HEADER(Callee)
 
-    bool congruentTo(MDefinition * const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
 
     static MCallee *New() {
         return new MCallee();
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
@@ -2028,17 +2028,17 @@ class MCompare
             return AliasSet::Store(AliasSet::Any);
         JS_ASSERT(compareType_ <= Compare_Value);
         return AliasSet::None();
     }
 
     void printOpcode(FILE *fp) const;
 
   protected:
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!MBinaryInstruction::congruentTo(ins))
             return false;
         return compareType() == ins->toCompare()->compareType() &&
                jsop() == ins->toCompare()->jsop();
     }
 };
 
 // Takes a typed value and returns an untyped value.
@@ -2064,17 +2064,17 @@ class MBox : public MUnaryInstruction
     static MBox *New(MDefinition *ins)
     {
         // Cannot box a box.
         JS_ASSERT(ins->type() != MIRType_Value);
 
         return new MBox(ins);
     }
 
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 // Note: the op may have been inverted during lowering (to put constants in a
@@ -2143,17 +2143,17 @@ class MUnbox : public MUnaryInstruction,
         JS_ASSERT(fallible());
         return mode() == Fallible
                ? Bailout_Normal
                : Bailout_TypeBarrier;
     }
     bool fallible() const {
         return mode() != Infallible;
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!ins->isUnbox() || ins->toUnbox()->mode() != mode())
             return false;
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     void printOpcode(FILE *fp) const;
@@ -2561,17 +2561,17 @@ class MToDouble
         return conversion_;
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!ins->isToDouble() || ins->toToDouble()->conversion() != conversion())
             return false;
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 
@@ -2593,17 +2593,17 @@ class MAsmJSUnsignedToDouble
 
   public:
     INSTRUCTION_HEADER(AsmJSUnsignedToDouble);
     static MAsmJSUnsignedToDouble *NewAsmJS(MDefinition *def) {
         return new MAsmJSUnsignedToDouble(def);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 // Converts a primitive (either typed or untyped) to an int32. If the input is
@@ -2635,17 +2635,17 @@ class MToInt32 : public MUnaryInstructio
 
     bool canBeNegativeZero() {
         return canBeNegativeZero_;
     }
     void setCanBeNegativeZero(bool negativeZero) {
         canBeNegativeZero_ = negativeZero;
     }
 
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     void computeRange();
 };
@@ -2667,17 +2667,17 @@ class MTruncateToInt32 : public MUnaryIn
         return new MTruncateToInt32(def);
     }
     static MTruncateToInt32 *NewAsmJS(MDefinition *def) {
         return new MTruncateToInt32(def);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
 
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 
     void computeRange();
     bool isOperandTruncated(size_t index) const;
@@ -2697,17 +2697,17 @@ class MToString : public MUnaryInstructi
     INSTRUCTION_HEADER(ToString)
     static MToString *New(MDefinition *def)
     {
         return new MToString(def);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
 
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         JS_ASSERT(input()->type() < MIRType_Object);
         return AliasSet::None();
     }
 };
 
@@ -2730,17 +2730,17 @@ class MBitNot
 
     TypePolicy *typePolicy() {
         return this;
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
     void infer();
 
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         if (specialization_ == MIRType_None)
             return AliasSet::Store(AliasSet::Any);
         return AliasSet::None();
     }
     void computeRange();
@@ -2826,17 +2826,17 @@ class MBinaryBitwiseInstruction
 
     MDefinition *foldsTo(bool useValueNumbers);
     MDefinition *foldUnnecessaryBitop();
     virtual MDefinition *foldIfZero(size_t operand) = 0;
     virtual MDefinition *foldIfNegOne(size_t operand) = 0;
     virtual MDefinition *foldIfEqual()  = 0;
     virtual void infer(BaselineInspector *inspector, jsbytecode *pc);
 
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         if (specialization_ >= MIRType_Object)
             return AliasSet::Store(AliasSet::Any);
         return AliasSet::None();
     }
 
@@ -3040,17 +3040,17 @@ class MBinaryArithInstruction
     void infer(BaselineInspector *inspector,
                jsbytecode *pc, bool overflowed);
 
     void setInt32() {
         specialization_ = MIRType_Int32;
         setResultType(MIRType_Int32);
     }
 
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return MBinaryInstruction::congruentTo(ins);
     }
     AliasSet getAliasSet() const {
         if (specialization_ >= MIRType_Object)
             return AliasSet::Store(AliasSet::Any);
         return AliasSet::None();
     }
 
@@ -3089,17 +3089,17 @@ class MMinMax
     }
     MIRType specialization() const {
         return specialization_;
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!ins->isMinMax())
             return false;
         if (isMax() != ins->toMinMax()->isMax())
             return false;
         return congruentIfOperandsEqual(ins);
     }
 
     AliasSet getAliasSet() const {
@@ -3136,17 +3136,17 @@ class MAbs
         return ins;
     }
     MDefinition *num() const {
         return getOperand(0);
     }
     TypePolicy *typePolicy() {
         return this;
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     bool fallible() const;
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     void computeRange();
@@ -3174,17 +3174,17 @@ class MSqrt
         return new MSqrt(num);
     }
     MDefinition *num() const {
         return getOperand(0);
     }
     TypePolicy *typePolicy() {
         return this;
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
@@ -3213,17 +3213,17 @@ class MAtan2
     MDefinition *x() const {
         return getOperand(1);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
 
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 
     bool possiblyCalls() const {
@@ -3251,17 +3251,17 @@ class MPow
     }
 
     MDefinition *input() const {
         return lhs();
     }
     MDefinition *power() const {
         return rhs();
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     TypePolicy *typePolicy() {
         return this;
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
@@ -3282,17 +3282,17 @@ class MPowHalf
         setMovable();
     }
 
   public:
     INSTRUCTION_HEADER(PowHalf)
     static MPowHalf *New(MDefinition *input) {
         return new MPowHalf(input);
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     TypePolicy *typePolicy() {
         return this;
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
@@ -3370,17 +3370,17 @@ class MMathFunction
         return function_;
     }
     MathCache *cache() const {
         return cache_;
     }
     TypePolicy *typePolicy() {
         return this;
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!ins->isMathFunction())
             return false;
         if (ins->toMathFunction()->function() != function())
             return false;
         return congruentIfOperandsEqual(ins);
     }
 
     AliasSet getAliasSet() const {
@@ -3664,17 +3664,17 @@ class MConcat
     INSTRUCTION_HEADER(Concat)
     static MConcat *New(MDefinition *left, MDefinition *right) {
         return new MConcat(left, right);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 class MConcatPar
@@ -3707,17 +3707,17 @@ class MConcatPar
     }
     MDefinition *rhs() const {
         return getOperand(2);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 class MCharCodeAt
@@ -3857,17 +3857,17 @@ class MPhi MOZ_FINAL : public MDefinitio
     void addInput(MDefinition *ins);
 
     // Appends a new input to the input vector. May call realloc().
     // Prefer reserveLength() and addInput() instead, where possible.
     bool addInputSlow(MDefinition *ins, bool *ptypeChange = NULL);
 
     MDefinition *foldsTo(bool useValueNumbers);
 
-    bool congruentTo(MDefinition * const &ins) const;
+    bool congruentTo(MDefinition *ins) const;
 
     bool isIterator() const {
         return isIterator_;
     }
     void setIterator() {
         isIterator_ = true;
     }
 
@@ -4293,17 +4293,17 @@ class MSlots
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
     MDefinition *object() const {
         return getOperand(0);
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::Load(AliasSet::ObjectFields);
     }
 };
 
 // Returns obj->elements.
@@ -4326,17 +4326,17 @@ class MElements
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
     MDefinition *object() const {
         return getOperand(0);
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::Load(AliasSet::ObjectFields);
     }
 };
 
 // A constant value for some object's array elements or typed array elements.
@@ -4363,17 +4363,17 @@ class MConstantElements : public MNullar
     }
 
     void printOpcode(FILE *fp) const;
 
     HashNumber valueHash() const {
         return (HashNumber)(size_t) value_;
     }
 
-    bool congruentTo(MDefinition * const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return ins->isConstantElements() && ins->toConstantElements()->value() == value();
     }
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
@@ -4394,17 +4394,17 @@ class MConvertElementsToDoubles
 
     static MConvertElementsToDoubles *New(MDefinition *elements) {
         return new MConvertElementsToDoubles(elements);
     }
 
     MDefinition *elements() const {
         return getOperand(0);
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         // This instruction can read and write to the elements' contents.
         // However, it is alright to hoist this from loops which explicitly
         // read or write to the elements: such reads and writes will use double
         // values and can be reordered freely wrt this conversion, except that
         // definite double loads must follow the conversion. The latter
@@ -4440,17 +4440,17 @@ class MMaybeToDoubleElement
     }
 
     MDefinition *elements() const {
         return getOperand(0);
     }
     MDefinition *value() const {
         return getOperand(1);
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::Load(AliasSet::ObjectFields);
     }
 };
 
 // Load a dense array's initialized length from an elements vector.
@@ -4469,17 +4469,17 @@ class MInitializedLength
 
     static MInitializedLength *New(MDefinition *elements) {
         return new MInitializedLength(elements);
     }
 
     MDefinition *elements() const {
         return getOperand(0);
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::Load(AliasSet::ObjectFields);
     }
 };
 
 // Set a dense array's initialized length to an elements vector.
@@ -4522,17 +4522,17 @@ class MArrayLength
         setMovable();
     }
 
     INSTRUCTION_HEADER(ArrayLength)
 
     MDefinition *elements() const {
         return getOperand(0);
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::Load(AliasSet::ObjectFields);
     }
 };
 
 // Read the length of a typed array.
@@ -4555,17 +4555,17 @@ class MTypedArrayLength
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
     MDefinition *object() const {
         return getOperand(0);
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         // The typed array |length| property is immutable, so there is no
         // implicit dependency.
         return AliasSet::None();
     }
 };
@@ -4590,17 +4590,17 @@ class MTypedArrayElements
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
     MDefinition *object() const {
         return getOperand(0);
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::Load(AliasSet::ObjectFields);
     }
 };
 
 // Perform !-operation
@@ -4693,17 +4693,17 @@ class MBoundsCheck
         minimum_ = n;
     }
     int32_t maximum() const {
         return maximum_;
     }
     void setMaximum(int32_t n) {
         maximum_ = n;
     }
-    bool congruentTo(MDefinition * const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!ins->isBoundsCheck())
             return false;
         MBoundsCheck *other = ins->toBoundsCheck();
         if (minimum() != other->minimum() || maximum() != other->maximum())
             return false;
         return congruentIfOperandsEqual(other);
     }
     virtual AliasSet getAliasSet() const {
@@ -5456,17 +5456,17 @@ class MClampToUint8
         return new MClampToUint8(input);
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
 
     TypePolicy *typePolicy() {
         return this;
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     void computeRange();
 };
 
@@ -5496,17 +5496,17 @@ class MLoadFixedSlot
     }
 
     MDefinition *object() const {
         return getOperand(0);
     }
     size_t slot() const {
         return slot_;
     }
-    bool congruentTo(MDefinition * const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!ins->isLoadFixedSlot())
             return false;
         if (slot() != ins->toLoadFixedSlot()->slot())
             return false;
         return congruentIfOperandsEqual(ins);
     }
 
     AliasSet getAliasSet() const {
@@ -5687,17 +5687,17 @@ class MGetPropertyCache
     bool allowGetters() const {
         return allowGetters_;
     }
     void setAllowGetters() {
         allowGetters_ = true;
     }
     TypePolicy *typePolicy() { return this; }
 
-    bool congruentTo(MDefinition * const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!idempotent_)
             return false;
         if (!ins->isGetPropertyCache())
             return false;
         if (name() != ins->toGetPropertyCache()->name())
             return false;
         return congruentIfOperandsEqual(ins);
     }
@@ -5744,17 +5744,17 @@ class MGetPropertyPolymorphic
 
   public:
     INSTRUCTION_HEADER(GetPropertyPolymorphic)
 
     static MGetPropertyPolymorphic *New(MDefinition *obj, HandlePropertyName name) {
         return new MGetPropertyPolymorphic(obj, name);
     }
 
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!ins->isGetPropertyPolymorphic())
             return false;
         if (name() != ins->toGetPropertyPolymorphic()->name())
             return false;
         return congruentIfOperandsEqual(ins);
     }
 
     TypePolicy *typePolicy() {
@@ -6260,17 +6260,17 @@ class MGuardShape
         return getOperand(0);
     }
     const Shape *shape() const {
         return shape_;
     }
     BailoutKind bailoutKind() const {
         return bailoutKind_;
     }
-    bool congruentTo(MDefinition * const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!ins->isGuardShape())
             return false;
         if (shape() != ins->toGuardShape()->shape())
             return false;
         if (bailoutKind() != ins->toGuardShape()->bailoutKind())
             return false;
         return congruentIfOperandsEqual(ins);
     }
@@ -6312,17 +6312,17 @@ class MGuardObjectType
         return getOperand(0);
     }
     const types::TypeObject *typeObject() const {
         return typeObject_;
     }
     bool bailOnEquality() const {
         return bailOnEquality_;
     }
-    bool congruentTo(MDefinition * const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!ins->isGuardObjectType())
             return false;
         if (typeObject() != ins->toGuardObjectType()->typeObject())
             return false;
         if (bailOnEquality() != ins->toGuardObjectType()->bailOnEquality())
             return false;
         return congruentIfOperandsEqual(ins);
     }
@@ -6357,17 +6357,17 @@ class MGuardClass
         return this;
     }
     MDefinition *obj() const {
         return getOperand(0);
     }
     const Class *getClass() const {
         return class_;
     }
-    bool congruentTo(MDefinition * const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!ins->isGuardClass())
             return false;
         if (getClass() != ins->toGuardClass()->getClass())
             return false;
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::Load(AliasSet::ObjectFields);
@@ -6402,17 +6402,17 @@ class MLoadSlot
     }
     MDefinition *slots() const {
         return getOperand(0);
     }
     uint32_t slot() const {
         return slot_;
     }
 
-    bool congruentTo(MDefinition * const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!ins->isLoadSlot())
             return false;
         if (slot() != ins->toLoadSlot()->slot())
             return false;
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         JS_ASSERT(slots()->type() == MIRType_Slots);
@@ -7035,17 +7035,17 @@ class MGetDOMProperty
     MDefinition *object() {
         return getOperand(0);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
 
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         if (!isDomPure())
             return false;
 
         if (!ins->isGetDOMProperty())
             return false;
 
         // Checking the jitinfo is the same as checking the constant function
         if (!(info() == ins->toGetDOMProperty()->info()))
@@ -7092,17 +7092,17 @@ class MStringLength
 
     TypePolicy *typePolicy() {
         return this;
     }
 
     MDefinition *string() const {
         return getOperand(0);
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         // The string |length| property is immutable, so there is no
         // implicit dependency.
         return AliasSet::None();
     }
 };
@@ -7400,17 +7400,17 @@ class MArgumentsLength : public MNullary
 
   public:
     INSTRUCTION_HEADER(ArgumentsLength)
 
     static MArgumentsLength *New() {
         return new MArgumentsLength();
     }
 
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         // Arguments |length| cannot be mutated by Ion Code.
         return AliasSet::None();
    }
 };
 
@@ -7435,17 +7435,17 @@ class MGetArgument
 
     MDefinition *index() const {
         return getOperand(0);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
-    bool congruentTo(MDefinition *const &ins) const {
+    bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 class MRestCommon
@@ -7615,17 +7615,17 @@ class MTypeBarrier
                              BailoutKind bailoutKind) {
         return new MTypeBarrier(def, types, bailoutKind);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
 
-    bool congruentTo(MDefinition * const &def) const {
+    bool congruentTo(MDefinition *def) const {
         return false;
     }
     BailoutKind bailoutKind() const {
         return bailoutKind_;
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
--- a/js/src/ion/RegisterAllocator.cpp
+++ b/js/src/ion/RegisterAllocator.cpp
@@ -448,17 +448,17 @@ AllocationIntegrityState::dump()
 }
 
 const CodePosition CodePosition::MAX(UINT_MAX);
 const CodePosition CodePosition::MIN(0);
 
 bool
 RegisterAllocator::init()
 {
-    if (!insData.init(lir->mir(), graph.numInstructions()))
+    if (!insData.init(mir, graph.numInstructions()))
         return false;
 
     for (size_t i = 0; i < graph.numBlocks(); i++) {
         LBlock *block = graph.getBlock(i);
         for (LInstructionIterator ins = block->begin(); ins != block->end(); ins++)
             insData[*ins].init(*ins, block);
         for (size_t j = 0; j < block->numPhis(); j++) {
             LPhi *phi = block->getPhi(j);
--- a/js/src/ion/RegisterAllocator.h
+++ b/js/src/ion/RegisterAllocator.h
@@ -292,38 +292,36 @@ class RegisterAllocator
     LIRGraph &graph;
 
     // Pool of all registers that should be considered allocateable
     RegisterSet allRegisters_;
 
     // Computed data
     InstructionDataMap insData;
 
-  public:
     RegisterAllocator(MIRGenerator *mir, LIRGenerator *lir, LIRGraph &graph)
       : mir(mir),
         lir(lir),
         graph(graph),
         allRegisters_(RegisterSet::All())
     {
-        if (FramePointer != InvalidReg && lir->mir()->instrumentedProfiling())
+        if (FramePointer != InvalidReg && mir->instrumentedProfiling())
             allRegisters_.take(AnyRegister(FramePointer));
 #if defined(JS_CPU_X64)
         if (mir->compilingAsmJS())
             allRegisters_.take(AnyRegister(HeapReg));
 #elif defined(JS_CPU_ARM)
         if (mir->compilingAsmJS()) {
             allRegisters_.take(AnyRegister(HeapReg));
             allRegisters_.take(AnyRegister(GlobalReg));
             allRegisters_.take(AnyRegister(NANReg));
         }
 #endif
     }
 
-  protected:
     bool init();
 
     CodePosition outputOf(uint32_t pos) const {
         return CodePosition(pos, CodePosition::OUTPUT);
     }
     CodePosition outputOf(const LInstruction *ins) const {
         return CodePosition(ins->id(), CodePosition::OUTPUT);
     }
--- a/js/src/ion/shared/Assembler-shared.h
+++ b/js/src/ion/shared/Assembler-shared.h
@@ -2,17 +2,16 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 ion_shared_Assembler_shared_h
 #define ion_shared_Assembler_shared_h
 
-#include "mozilla/DebugOnly.h"
 #include "mozilla/PodOperations.h"
 
 #include <limits.h>
 
 #include "ion/IonAllocPolicy.h"
 #include "ion/Registers.h"
 #include "ion/RegisterSets.h"
 
@@ -197,27 +196,24 @@ struct LabelBase
   protected:
     // offset_ >= 0 means that the label is either bound or has incoming
     // uses and needs to be bound.
     int32_t offset_ : 31;
     bool bound_   : 1;
 
     // Disallow assignment.
     void operator =(const LabelBase &label);
-    static int id_count;
   public:
-    mozilla::DebugOnly <int> id;
     static const int32_t INVALID_OFFSET = -1;
 
-    LabelBase() : offset_(INVALID_OFFSET), bound_(false), id(id_count++)
+    LabelBase() : offset_(INVALID_OFFSET), bound_(false)
     { }
     LabelBase(const LabelBase &label)
       : offset_(label.offset_),
-        bound_(label.bound_),
-        id(id_count++)
+        bound_(label.bound_)
     { }
 
     // If the label is bound, all incoming edges have been patched and any
     // future incoming edges will be immediately patched.
     bool bound() const {
         return bound_;
     }
     int32_t offset() const {
--- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp
@@ -27,22 +27,16 @@ using mozilla::FloorLog2;
 namespace js {
 namespace ion {
 
 CodeGeneratorX86Shared::CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm)
   : CodeGeneratorShared(gen, graph, masm)
 {
 }
 
-double
-test(double x, double y)
-{
-    return x + y;
-}
-
 bool
 CodeGeneratorX86Shared::generatePrologue()
 {
     // Note that this automatically sets MacroAssembler::framePushed().
     masm.reserveStack(frameSize());
 
     return true;
 }
--- a/js/src/jsatom.h
+++ b/js/src/jsatom.h
@@ -48,26 +48,16 @@ struct JsidHasher
 
 /*
  * Return a printable, lossless char[] representation of a string-type atom.
  * The lifetime of the result matches the lifetime of bytes.
  */
 extern const char *
 AtomToPrintableString(ExclusiveContext *cx, JSAtom *atom, JSAutoByteString *bytes);
 
-/* Compute a hash function from chars/length. */
-inline uint32_t
-HashChars(const jschar *chars, size_t length)
-{
-    uint32_t h = 0;
-    for (; length; chars++, length--)
-        h = JS_ROTATE_LEFT32(h, 4) ^ *chars;
-    return h;
-}
-
 class AtomStateEntry
 {
     uintptr_t bits;
 
     static const uintptr_t NO_TAG_MASK = uintptr_t(-1) - 1;
 
   public:
     AtomStateEntry() : bits(0) {}
@@ -100,17 +90,17 @@ struct AtomHasher
         const jschar    *chars;
         size_t          length;
         const JSAtom    *atom; /* Optional. */
 
         Lookup(const jschar *chars, size_t length) : chars(chars), length(length), atom(NULL) {}
         inline Lookup(const JSAtom *atom);
     };
 
-    static HashNumber hash(const Lookup &l) { return HashChars(l.chars, l.length); }
+    static HashNumber hash(const Lookup &l) { return mozilla::HashString(l.chars, l.length); }
     static inline bool match(const AtomStateEntry &entry, const Lookup &lookup);
 };
 
 typedef HashSet<AtomStateEntry, AtomHasher, SystemAllocPolicy> AtomSet;
 
 class PropertyName;
 
 }  /* namespace js */
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -990,17 +990,17 @@ struct StackShape
         flags(uint8_t(flags)),
         shortid(int16_t(shortid))
     {
         JS_ASSERT(base);
         JS_ASSERT(!JSID_IS_VOID(propid));
         JS_ASSERT(slot <= SHAPE_INVALID_SLOT);
     }
 
-    StackShape(Shape *const &shape)
+    StackShape(Shape *shape)
       : base(shape->base()->unowned()),
         propid(shape->propidRef()),
         slot_(shape->slotInfo & Shape::SLOT_MASK),
         attrs(shape->attrs),
         flags(shape->flags),
         shortid(shape->shortid_)
     {}
 
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -1367,16 +1367,42 @@ RestyleManager::ProcessPendingRestyles()
     // We probably wasted a lot of work up above, but this seems safest
     // and it should be rarely used.
     // This might add us as a refresh observer again; that's ok.
     RebuildAllStyleData(nsChangeHint(0));
   }
 }
 
 void
+RestyleManager::BeginProcessingRestyles()
+{
+  // Make sure to not rebuild quote or counter lists while we're
+  // processing restyles
+  mPresContext->FrameConstructor()->BeginUpdate();
+
+  mInStyleRefresh = true;
+}
+
+void
+RestyleManager::EndProcessingRestyles()
+{
+  FlushOverflowChangedTracker();
+
+  // Set mInStyleRefresh to false now, since the EndUpdate call might
+  // add more restyles.
+  mInStyleRefresh = false;
+
+  mPresContext->FrameConstructor()->EndUpdate();
+
+#ifdef DEBUG
+  mPresContext->PresShell()->VerifyStyleTree();
+#endif
+}
+
+void
 RestyleManager::PostRestyleEventCommon(Element* aElement,
                                        nsRestyleHint aRestyleHint,
                                        nsChangeHint aMinChangeHint,
                                        bool aForAnimation)
 {
   if (MOZ_UNLIKELY(mPresContext->PresShell()->IsDestroying())) {
     return;
   }
@@ -1572,25 +1598,21 @@ VerifyStyleTree(nsPresContext* aPresCont
         else { // regular frame
           VerifyStyleTree(aPresContext, child, nullptr);
         }
       }
     }
   }
 
   // do additional contexts
-  int32_t contextIndex = -1;
-  while (1) {
-    nsStyleContext* extraContext = aFrame->GetAdditionalStyleContext(++contextIndex);
-    if (extraContext) {
-      VerifyContextParent(aPresContext, aFrame, extraContext, context);
-    }
-    else {
-      break;
-    }
+  int32_t contextIndex = 0;
+  for (nsStyleContext* extraContext;
+       (extraContext = aFrame->GetAdditionalStyleContext(contextIndex));
+       ++contextIndex) {
+    VerifyContextParent(aPresContext, aFrame, extraContext, context);
   }
 }
 
 void
 RestyleManager::DebugVerifyStyleTree(nsIFrame* aFrame)
 {
   if (aFrame) {
     nsStyleContext* context = aFrame->StyleContext();
@@ -1635,17 +1657,17 @@ ElementForStyleContext(nsIContent* aPare
                        nsCSSPseudoElements::Type aPseudoType)
 {
   // We don't expect XUL tree stuff here.
   NS_PRECONDITION(aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement ||
                   aPseudoType == nsCSSPseudoElements::ePseudo_AnonBox ||
                   aPseudoType < nsCSSPseudoElements::ePseudo_PseudoElementCount,
                   "Unexpected pseudo");
   // XXX see the comments about the various element confusion in
-  // ReResolveStyleContext.
+  // ElementRestyler::Restyle.
   if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) {
     return aFrame->GetContent()->AsElement();
   }
 
   if (aPseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
     return nullptr;
   }
 
@@ -1699,891 +1721,957 @@ RestyleManager::ReparentStyleContext(nsI
     do {
       ReparentStyleContext(outOfFlow);
     } while ((outOfFlow = outOfFlow->GetNextContinuation()));
   }
 
   // DO NOT verify the style tree before reparenting.  The frame
   // tree has already been changed, so this check would just fail.
   nsStyleContext* oldContext = aFrame->StyleContext();
-  // XXXbz can oldContext really ever be null?
-  if (oldContext) {
-    nsRefPtr<nsStyleContext> newContext;
-    nsIFrame* providerFrame = aFrame->GetParentStyleContextFrame();
-    bool isChild = providerFrame && providerFrame->GetParent() == aFrame;
-    nsStyleContext* newParentContext = nullptr;
-    nsIFrame* providerChild = nullptr;
-    if (isChild) {
-      ReparentStyleContext(providerFrame);
-      newParentContext = providerFrame->StyleContext();
-      providerChild = providerFrame;
-    } else if (providerFrame) {
-      newParentContext = providerFrame->StyleContext();
-    } else {
-      NS_NOTREACHED("Reparenting something that has no usable parent? "
-                    "Shouldn't happen!");
-    }
-    // XXX need to do something here to produce the correct style context for
-    // an IB split whose first inline part is inside a first-line frame.
-    // Currently the first IB anonymous block's style context takes the first
-    // part's style context as parent, which is wrong since first-line style
-    // should not apply to the anonymous block.
+
+  nsRefPtr<nsStyleContext> newContext;
+  nsIFrame* providerFrame = aFrame->GetParentStyleContextFrame();
+  bool isChild = providerFrame && providerFrame->GetParent() == aFrame;
+  nsStyleContext* newParentContext = nullptr;
+  nsIFrame* providerChild = nullptr;
+  if (isChild) {
+    ReparentStyleContext(providerFrame);
+    newParentContext = providerFrame->StyleContext();
+    providerChild = providerFrame;
+  } else if (providerFrame) {
+    newParentContext = providerFrame->StyleContext();
+  } else {
+    NS_NOTREACHED("Reparenting something that has no usable parent? "
+                  "Shouldn't happen!");
+  }
+  // XXX need to do something here to produce the correct style context for
+  // an IB split whose first inline part is inside a first-line frame.
+  // Currently the first IB anonymous block's style context takes the first
+  // part's style context as parent, which is wrong since first-line style
+  // should not apply to the anonymous block.
 
 #ifdef DEBUG
-    {
-      // Check that our assumption that continuations of the same
-      // pseudo-type and with the same style context parent have the
-      // same style context is valid before the reresolution.  (We need
-      // to check the pseudo-type and style context parent because of
-      // :first-letter and :first-line, where we create styled and
-      // unstyled letter/line frames distinguished by pseudo-type, and
-      // then need to distinguish their descendants based on having
-      // different parents.)
-      nsIFrame *nextContinuation = aFrame->GetNextContinuation();
-      if (nextContinuation) {
-        nsStyleContext *nextContinuationContext =
-          nextContinuation->StyleContext();
-        NS_ASSERTION(oldContext == nextContinuationContext ||
-                     oldContext->GetPseudo() !=
-                       nextContinuationContext->GetPseudo() ||
-                     oldContext->GetParent() !=
-                       nextContinuationContext->GetParent(),
-                     "continuations should have the same style context");
-      }
+  {
+    // Check that our assumption that continuations of the same
+    // pseudo-type and with the same style context parent have the
+    // same style context is valid before the reresolution.  (We need
+    // to check the pseudo-type and style context parent because of
+    // :first-letter and :first-line, where we create styled and
+    // unstyled letter/line frames distinguished by pseudo-type, and
+    // then need to distinguish their descendants based on having
+    // different parents.)
+    nsIFrame *nextContinuation = aFrame->GetNextContinuation();
+    if (nextContinuation) {
+      nsStyleContext *nextContinuationContext =
+        nextContinuation->StyleContext();
+      NS_ASSERTION(oldContext == nextContinuationContext ||
+                   oldContext->GetPseudo() !=
+                     nextContinuationContext->GetPseudo() ||
+                   oldContext->GetParent() !=
+                     nextContinuationContext->GetParent(),
+                   "continuations should have the same style context");
     }
+  }
 #endif
 
-    nsIFrame *prevContinuation =
-      GetPrevContinuationWithPossiblySameStyle(aFrame);
-    nsStyleContext *prevContinuationContext;
-    bool copyFromContinuation =
-      prevContinuation &&
-      (prevContinuationContext = prevContinuation->StyleContext())
-        ->GetPseudo() == oldContext->GetPseudo() &&
-       prevContinuationContext->GetParent() == newParentContext;
-    if (copyFromContinuation) {
-      // Just use the style context from the frame's previous
-      // continuation (see assertion about aFrame->GetNextContinuation()
-      // above, which we would have previously hit for aFrame's previous
-      // continuation).
-      newContext = prevContinuationContext;
-    } else {
-      nsIFrame* parentFrame = aFrame->GetParent();
-      Element* element =
-        ElementForStyleContext(parentFrame ? parentFrame->GetContent() : nullptr,
-                               aFrame,
-                               oldContext->GetPseudoType());
-      newContext = mPresContext->StyleSet()->
-                     ReparentStyleContext(oldContext, newParentContext, element);
-    }
+  nsIFrame *prevContinuation =
+    GetPrevContinuationWithPossiblySameStyle(aFrame);
+  nsStyleContext *prevContinuationContext;
+  bool copyFromContinuation =
+    prevContinuation &&
+    (prevContinuationContext = prevContinuation->StyleContext())
+      ->GetPseudo() == oldContext->GetPseudo() &&
+     prevContinuationContext->GetParent() == newParentContext;
+  if (copyFromContinuation) {
+    // Just use the style context from the frame's previous
+    // continuation (see assertion about aFrame->GetNextContinuation()
+    // above, which we would have previously hit for aFrame's previous
+    // continuation).
+    newContext = prevContinuationContext;
+  } else {
+    nsIFrame* parentFrame = aFrame->GetParent();
+    Element* element =
+      ElementForStyleContext(parentFrame ? parentFrame->GetContent() : nullptr,
+                             aFrame,
+                             oldContext->GetPseudoType());
+    newContext = mPresContext->StyleSet()->
+                   ReparentStyleContext(oldContext, newParentContext, element);
+  }
 
-    if (newContext) {
-      if (newContext != oldContext) {
-        // We probably don't want to initiate transitions from
-        // ReparentStyleContext, since we call it during frame
-        // construction rather than in response to dynamic changes.
-        // Also see the comment at the start of
-        // nsTransitionManager::ConsiderStartingTransition.
+  if (newContext) {
+    if (newContext != oldContext) {
+      // We probably don't want to initiate transitions from
+      // ReparentStyleContext, since we call it during frame
+      // construction rather than in response to dynamic changes.
+      // Also see the comment at the start of
+      // nsTransitionManager::ConsiderStartingTransition.
 #if 0
-        if (!copyFromContinuation) {
-          TryStartingTransition(mPresContext, aFrame->GetContent(),
-                                oldContext, &newContext);
-        }
+      if (!copyFromContinuation) {
+        TryStartingTransition(mPresContext, aFrame->GetContent(),
+                              oldContext, &newContext);
+      }
 #endif
 
-        // Make sure to call CalcStyleDifference so that the new context ends
-        // up resolving all the structs the old context resolved.
-        DebugOnly<nsChangeHint> styleChange =
-          oldContext->CalcStyleDifference(newContext, nsChangeHint(0));
-        // The style change is always 0 because we have the same rulenode and
-        // CalcStyleDifference optimizes us away.  That's OK, though:
-        // reparenting should never trigger a frame reconstruct, and whenever
-        // it's happening we already plan to reflow and repaint the frames.
-        NS_ASSERTION(!(styleChange & nsChangeHint_ReconstructFrame),
-                     "Our frame tree is likely to be bogus!");
+      // Make sure to call CalcStyleDifference so that the new context ends
+      // up resolving all the structs the old context resolved.
+      DebugOnly<nsChangeHint> styleChange =
+        oldContext->CalcStyleDifference(newContext, nsChangeHint(0));
+      // The style change is always 0 because we have the same rulenode and
+      // CalcStyleDifference optimizes us away.  That's OK, though:
+      // reparenting should never trigger a frame reconstruct, and whenever
+      // it's happening we already plan to reflow and repaint the frames.
+      NS_ASSERTION(!(styleChange & nsChangeHint_ReconstructFrame),
+                   "Our frame tree is likely to be bogus!");
 
-        aFrame->SetStyleContext(newContext);
+      aFrame->SetStyleContext(newContext);
 
-        nsIFrame::ChildListIterator lists(aFrame);
-        for (; !lists.IsDone(); lists.Next()) {
-          nsFrameList::Enumerator childFrames(lists.CurrentList());
-          for (; !childFrames.AtEnd(); childFrames.Next()) {
-            nsIFrame* child = childFrames.get();
-            // only do frames that are in flow
-            if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
-                child != providerChild) {
+      nsIFrame::ChildListIterator lists(aFrame);
+      for (; !lists.IsDone(); lists.Next()) {
+        nsFrameList::Enumerator childFrames(lists.CurrentList());
+        for (; !childFrames.AtEnd(); childFrames.Next()) {
+          nsIFrame* child = childFrames.get();
+          // only do frames that are in flow
+          if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
+              child != providerChild) {
 #ifdef DEBUG
-              if (nsGkAtoms::placeholderFrame == child->GetType()) {
-                nsIFrame* outOfFlowFrame =
-                  nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
-                NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
+            if (nsGkAtoms::placeholderFrame == child->GetType()) {
+              nsIFrame* outOfFlowFrame =
+                nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
+              NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
 
-                NS_ASSERTION(outOfFlowFrame != providerChild,
-                             "Out of flow provider?");
-              }
+              NS_ASSERTION(outOfFlowFrame != providerChild,
+                           "Out of flow provider?");
+            }
 #endif
-              ReparentStyleContext(child);
-            }
+            ReparentStyleContext(child);
           }
         }
+      }
 
-        // If this frame is part of an IB split, then the style context of
-        // the next part of the split might be a child of our style context.
-        // Reparent its style context just in case one of our ancestors
-        // (split or not) hasn't done so already). It's not a problem to
-        // reparent the same frame twice because the "if (newContext !=
-        // oldContext)" check will prevent us from redoing work.
-        if ((aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
-            !aFrame->GetPrevContinuation()) {
-          nsIFrame* sib = static_cast<nsIFrame*>
-            (aFrame->Properties().Get(nsIFrame::IBSplitSpecialSibling()));
-          if (sib) {
-            ReparentStyleContext(sib);
-          }
+      // If this frame is part of an IB split, then the style context of
+      // the next part of the split might be a child of our style context.
+      // Reparent its style context just in case one of our ancestors
+      // (split or not) hasn't done so already). It's not a problem to
+      // reparent the same frame twice because the "if (newContext !=
+      // oldContext)" check will prevent us from redoing work.
+      if ((aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
+          !aFrame->GetPrevContinuation()) {
+        nsIFrame* sib = static_cast<nsIFrame*>
+          (aFrame->Properties().Get(nsIFrame::IBSplitSpecialSibling()));
+        if (sib) {
+          ReparentStyleContext(sib);
         }
+      }
 
-        // do additional contexts
-        int32_t contextIndex = -1;
-        while (1) {
-          nsStyleContext* oldExtraContext =
-            aFrame->GetAdditionalStyleContext(++contextIndex);
-          if (oldExtraContext) {
-            nsRefPtr<nsStyleContext> newExtraContext;
-            newExtraContext = mPresContext->StyleSet()->
-                                ReparentStyleContext(oldExtraContext,
-                                                     newContext, nullptr);
-            if (newExtraContext) {
-              if (newExtraContext != oldExtraContext) {
-                // Make sure to call CalcStyleDifference so that the new
-                // context ends up resolving all the structs the old context
-                // resolved.
-                styleChange =
-                  oldExtraContext->CalcStyleDifference(newExtraContext,
-                                                       nsChangeHint(0));
-                // The style change is always 0 because we have the same
-                // rulenode and CalcStyleDifference optimizes us away.  That's
-                // OK, though: reparenting should never trigger a frame
-                // reconstruct, and whenever it's happening we already plan to
-                // reflow and repaint the frames.
-                NS_ASSERTION(!(styleChange & nsChangeHint_ReconstructFrame),
-                             "Our frame tree is likely to be bogus!");
-              }
+      // do additional contexts
+      int32_t contextIndex = 0;
+      for (nsStyleContext* oldExtraContext;
+           (oldExtraContext = aFrame->GetAdditionalStyleContext(contextIndex));
+           ++contextIndex) {
+        nsRefPtr<nsStyleContext> newExtraContext;
+        newExtraContext = mPresContext->StyleSet()->
+                            ReparentStyleContext(oldExtraContext,
+                                                 newContext, nullptr);
+        if (newExtraContext) {
+          if (newExtraContext != oldExtraContext) {
+            // Make sure to call CalcStyleDifference so that the new
+            // context ends up resolving all the structs the old context
+            // resolved.
+            styleChange =
+              oldExtraContext->CalcStyleDifference(newExtraContext,
+                                                   nsChangeHint(0));
+            // The style change is always 0 because we have the same
+            // rulenode and CalcStyleDifference optimizes us away.  That's
+            // OK, though: reparenting should never trigger a frame
+            // reconstruct, and whenever it's happening we already plan to
+            // reflow and repaint the frames.
+            NS_ASSERTION(!(styleChange & nsChangeHint_ReconstructFrame),
+                         "Our frame tree is likely to be bogus!");
+          }
 
-              aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
-            }
-          }
-          else {
-            break;
-          }
+          aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
         }
+      }
 #ifdef DEBUG
-        VerifyStyleTree(mPresContext, aFrame, newParentContext);
+      VerifyStyleTree(mPresContext, aFrame, newParentContext);
 #endif
-      }
     }
   }
+
   return NS_OK;
 }
 
-static void
-CaptureChange(nsStyleContext* aOldContext, nsStyleContext* aNewContext,
-              nsIFrame* aFrame, nsIContent* aContent,
-              nsStyleChangeList* aChangeList,
-              /*inout*/nsChangeHint &aMinChange,
-              /*in*/nsChangeHint aParentHintsNotHandledForDescendants,
-              /*out*/nsChangeHint &aHintsNotHandledForDescendants,
-              nsChangeHint aChangeToAssume)
+ElementRestyler::ElementRestyler(nsPresContext* aPresContext,
+                                 nsIFrame* aFrame,
+                                 nsStyleChangeList* aChangeList,
+                                 nsChangeHint aHintsHandledByAncestors,
+                                 RestyleTracker& aRestyleTracker,
+                                 TreeMatchContext& aTreeMatchContext,
+                                 nsTArray<nsIContent*>&
+                                   aVisibleKidsOfHiddenElement)
+  : mPresContext(aPresContext)
+  , mFrame(aFrame)
+  , mParentContent(nullptr)
+    // XXXldb Why does it make sense to use aParentContent?  (See
+    // comment above assertion at start of ElementRestyler::Restyle.)
+  , mContent(mFrame->GetContent() ? mFrame->GetContent() : mParentContent)
+  , mChangeList(aChangeList)
+  , mHintsHandled(NS_SubtractHint(aHintsHandledByAncestors,
+                  NS_HintsNotHandledForDescendantsIn(aHintsHandledByAncestors)))
+  , mParentFrameHintsNotHandledForDescendants(nsChangeHint(0))
+  , mHintsNotHandledForDescendants(nsChangeHint(0))
+  , mRestyleTracker(aRestyleTracker)
+  , mTreeMatchContext(aTreeMatchContext)
+  , mResolvedChild(nullptr)
+  , mDesiredA11yNotifications(eSendAllNotifications)
+  , mKidsDesiredA11yNotifications(mDesiredA11yNotifications)
+  , mOurA11yNotification(eDontNotify)
+  , mVisibleKidsOfHiddenElement(aVisibleKidsOfHiddenElement)
 {
+}
+
+ElementRestyler::ElementRestyler(const ElementRestyler& aParentRestyler,
+                                 nsIFrame* aFrame,
+                                 uint32_t aConstructorFlags)
+  : mPresContext(aParentRestyler.mPresContext)
+  , mFrame(aFrame)
+  , mParentContent(aParentRestyler.mContent)
+    // XXXldb Why does it make sense to use aParentContent?  (See
+    // comment above assertion at start of ElementRestyler::Restyle.)
+  , mContent(mFrame->GetContent() ? mFrame->GetContent() : mParentContent)
+  , mChangeList(aParentRestyler.mChangeList)
+  , mHintsHandled(NS_SubtractHint(aParentRestyler.mHintsHandled,
+                  NS_HintsNotHandledForDescendantsIn(aParentRestyler.mHintsHandled)))
+  , mParentFrameHintsNotHandledForDescendants(
+      aParentRestyler.mHintsNotHandledForDescendants)
+  , mHintsNotHandledForDescendants(nsChangeHint(0))
+  , mRestyleTracker(aParentRestyler.mRestyleTracker)
+  , mTreeMatchContext(aParentRestyler.mTreeMatchContext)
+  , mResolvedChild(nullptr)
+  , mDesiredA11yNotifications(aParentRestyler.mKidsDesiredA11yNotifications)
+  , mKidsDesiredA11yNotifications(mDesiredA11yNotifications)
+  , mOurA11yNotification(eDontNotify)
+  , mVisibleKidsOfHiddenElement(aParentRestyler.mVisibleKidsOfHiddenElement)
+{
+  if (aConstructorFlags & FOR_OUT_OF_FLOW_CHILD) {
+    mHintsHandled = NS_SubtractHint(mHintsHandled, nsChangeHint_AllReflowHints);
+  }
+}
+
+ElementRestyler::ElementRestyler(ParentContextFromChildFrame,
+                                 const ElementRestyler& aParentRestyler,
+                                 nsIFrame* aFrame)
+  : mPresContext(aParentRestyler.mPresContext)
+  , mFrame(aFrame)
+  , mParentContent(aParentRestyler.mParentContent)
+    // XXXldb Why does it make sense to use aParentContent?  (See
+    // comment above assertion at start of ElementRestyler::Restyle.)
+  , mContent(mFrame->GetContent() ? mFrame->GetContent() : mParentContent)
+  , mChangeList(aParentRestyler.mChangeList)
+  , mHintsHandled(NS_SubtractHint(aParentRestyler.mHintsHandled,
+                  NS_HintsNotHandledForDescendantsIn(aParentRestyler.mHintsHandled)))
+  , mParentFrameHintsNotHandledForDescendants(
+      // assume the worst
+      nsChangeHint_Hints_NotHandledForDescendants)
+  , mHintsNotHandledForDescendants(nsChangeHint(0))
+  , mRestyleTracker(aParentRestyler.mRestyleTracker)
+  , mTreeMatchContext(aParentRestyler.mTreeMatchContext)
+  , mResolvedChild(nullptr)
+  , mDesiredA11yNotifications(aParentRestyler.mDesiredA11yNotifications)
+  , mKidsDesiredA11yNotifications(mDesiredA11yNotifications)
+  , mOurA11yNotification(eDontNotify)
+  , mVisibleKidsOfHiddenElement(aParentRestyler.mVisibleKidsOfHiddenElement)
+{
+}
+
+void
+ElementRestyler::CaptureChange(nsStyleContext* aOldContext,
+                               nsStyleContext* aNewContext,
+                               nsChangeHint aChangeToAssume)
+{
+  // Check some invariants about replacing one style context with another.
+  NS_ASSERTION(aOldContext->GetPseudo() == aNewContext->GetPseudo(),
+               "old and new style contexts should have the same pseudo");
+  NS_ASSERTION(aOldContext->GetPseudoType() == aNewContext->GetPseudoType(),
+               "old and new style contexts should have the same pseudo");
+
   nsChangeHint ourChange = aOldContext->CalcStyleDifference(aNewContext,
-                             aParentHintsNotHandledForDescendants);
+                             mParentFrameHintsNotHandledForDescendants);
   NS_ASSERTION(!(ourChange & nsChangeHint_AllReflowHints) ||
                (ourChange & nsChangeHint_NeedReflow),
                "Reflow hint bits set without actually asking for a reflow");
 
   // nsChangeHint_UpdateEffects is inherited, but it can be set due to changes
   // in inherited properties (fill and stroke).  Avoid propagating it into
   // text nodes.
   if ((ourChange & nsChangeHint_UpdateEffects) &&
-      aContent && !aContent->IsElement()) {
+      mContent && !mContent->IsElement()) {
     ourChange = NS_SubtractHint(ourChange, nsChangeHint_UpdateEffects);
   }
 
   NS_UpdateHint(ourChange, aChangeToAssume);
-  if (NS_UpdateHint(aMinChange, ourChange)) {
-    if (!(ourChange & nsChangeHint_ReconstructFrame) || aContent) {
-      aChangeList->AppendChange(aFrame, aContent, ourChange);
+  if (NS_UpdateHint(mHintsHandled, ourChange)) {
+    if (!(ourChange & nsChangeHint_ReconstructFrame) || mContent) {
+      mChangeList->AppendChange(mFrame, mContent, ourChange);
     }
   }
-  aHintsNotHandledForDescendants = NS_HintsNotHandledForDescendantsIn(ourChange);
+  NS_UpdateHint(mHintsNotHandledForDescendants,
+                NS_HintsNotHandledForDescendantsIn(ourChange));
 }
 
 /**
- * Recompute style for aFrame and accumulate changes into aChangeList
- * given that aMinChange is already accumulated for an ancestor.
- * aParentContent is the content node used to resolve the parent style
+ * Recompute style for mFrame and accumulate changes into mChangeList
+ * given that mHintsHandled is already accumulated for an ancestor.
+ * mParentContent is the content node used to resolve the parent style
  * context.  This means that, for pseudo-elements, it is the content
  * that should be used for selector matching (rather than the fake
  * content node attached to the frame).
- *
- * For aParentFrameHintsNotHandledForDescendants, see
- * nsStyleContext::CalcStyleDifference.
  */
-nsChangeHint
-RestyleManager::ReResolveStyleContext(nsPresContext     *aPresContext,
-                                      nsIFrame          *aFrame,
-                                      nsIContent        *aParentContent,
-                                      nsStyleChangeList *aChangeList,
-                                      nsChangeHint       aMinChange,
-                                      nsChangeHint       aParentFrameHintsNotHandledForDescendants,
-                                      nsRestyleHint      aRestyleHint,
-                                      RestyleTracker&    aRestyleTracker,
-                                      DesiredA11yNotifications aDesiredA11yNotifications,
-                                      nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
-                                      TreeMatchContext &aTreeMatchContext)
+void
+ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
 {
-  // We need to generate a new change list entry for every frame whose style
-  // comparision returns one of these hints. These hints don't automatically
-  // update all their descendant frames.
-  aMinChange = NS_SubtractHint(aMinChange, NS_HintsNotHandledForDescendantsIn(aMinChange));
-
   // It would be nice if we could make stronger assertions here; they
   // would let us simplify the ?: expressions below setting |content|
   // and |pseudoContent| in sensible ways as well as making what
-  // |localContent|, |content|, and |pseudoContent| mean make more
-  // sense.  However, we can't, because of frame trees like the one in
+  // |content| and |pseudoContent| mean, and their relationship to
+  // |mFrame->GetContent()|, make more sense.  However, we can't,
+  // because of frame trees like the one in
   // https://bugzilla.mozilla.org/show_bug.cgi?id=472353#c14 .  Once we
   // fix bug 242277 we should be able to make this make more sense.
-  NS_ASSERTION(aFrame->GetContent() || !aParentContent ||
-               !aParentContent->GetParent(),
+  NS_ASSERTION(mFrame->GetContent() || !mParentContent ||
+               !mParentContent->GetParent(),
                "frame must have content (unless at the top of the tree)");
+
+  if (mContent && mContent->IsElement()) {
+    mContent->OwnerDoc()->FlushPendingLinkUpdates();
+    RestyleTracker::RestyleData restyleData;
+    if (mRestyleTracker.GetRestyleData(mContent->AsElement(), &restyleData)) {
+      if (NS_UpdateHint(mHintsHandled, restyleData.mChangeHint)) {
+        mChangeList->AppendChange(mFrame, mContent, restyleData.mChangeHint);
+      }
+      aRestyleHint = nsRestyleHint(aRestyleHint | restyleData.mRestyleHint);
+    }
+  }
+
+  nsRestyleHint childRestyleHint = aRestyleHint;
+
+  if (childRestyleHint == eRestyle_Self) {
+    childRestyleHint = nsRestyleHint(0);
+  }
+
+  RestyleSelf(aRestyleHint);
+
+  RestyleChildren(childRestyleHint);
+}
+
+void
+ElementRestyler::RestyleSelf(nsRestyleHint aRestyleHint)
+{
   // XXXldb get new context from prev-in-flow if possible, to avoid
   // duplication.  (Or should we just let |GetContext| handle that?)
   // Getting the hint would be nice too, but that's harder.
 
   // XXXbryner we may be able to avoid some of the refcounting goop here.
   // We do need a reference to oldContext for the lifetime of this function, and it's possible
   // that the frame has the last reference to it, so AddRef it here.
 
   nsChangeHint assumeDifferenceHint = NS_STYLE_HINT_NONE;
-  // XXXbz oldContext should just be an nsRefPtr
-  nsStyleContext* oldContext = aFrame->StyleContext();
-  nsStyleSet* styleSet = aPresContext->StyleSet();
-
-  // XXXbz the nsIFrame constructor takes an nsStyleContext, so how
-  // could oldContext be null?
-  if (oldContext) {
-    oldContext->AddRef();
+  nsRefPtr<nsStyleContext> oldContext = mFrame->StyleContext();
+  nsStyleSet* styleSet = mPresContext->StyleSet();
 
 #ifdef ACCESSIBILITY
-    bool wasFrameVisible = nsIPresShell::IsAccessibilityActive() ?
-      oldContext->StyleVisibility()->IsVisible() : false;
+  mWasFrameVisible = nsIPresShell::IsAccessibilityActive() ?
+    oldContext->StyleVisibility()->IsVisible() : false;
 #endif
 
-    nsIAtom* const pseudoTag = oldContext->GetPseudo();
-    const nsCSSPseudoElements::Type pseudoType = oldContext->GetPseudoType();
-    nsIContent* localContent = aFrame->GetContent();
-    // |content| is the node that we used for rule matching of
-    // normal elements (not pseudo-elements) and for which we generate
-    // framechange hints if we need them.
-    // XXXldb Why does it make sense to use aParentContent?  (See
-    // comment above assertion at start of function.)
-    nsIContent* content = localContent ? localContent : aParentContent;
+  nsIAtom* const pseudoTag = oldContext->GetPseudo();
+  const nsCSSPseudoElements::Type pseudoType = oldContext->GetPseudoType();
+
+  nsStyleContext* parentContext;
+  // Get the frame providing the parent style context.  If it is a
+  // child, then resolve the provider first.
+  nsIFrame* providerFrame = mFrame->GetParentStyleContextFrame();
+  bool isChild = providerFrame && providerFrame->GetParent() == mFrame;
+  if (!isChild) {
+    if (providerFrame)
+      parentContext = providerFrame->StyleContext();
+    else
+      parentContext = nullptr;
+  }
+  else {
+    MOZ_ASSERT(providerFrame->GetContent() == mFrame->GetContent(),
+               "Postcondition for GetParentStyleContextFrame() violated. "
+               "That means we need to add the current element to the "
+               "ancestor filter.");
+
+    // resolve the provider here (before mFrame below).
+
+    // assumeDifferenceHint forces the parent's change to be also
+    // applied to this frame, no matter what
+    // nsStyleContext::CalcStyleDifference says. CalcStyleDifference
+    // can't be trusted because it assumes any changes to the parent
+    // style context provider will be automatically propagated to
+    // the frame(s) with child style contexts.
+
+    ElementRestyler providerRestyler(PARENT_CONTEXT_FROM_CHILD_FRAME,
+                                     *this, providerFrame);
+    providerRestyler.Restyle(aRestyleHint);
+    assumeDifferenceHint = providerRestyler.HintsHandledForFrame();
+
+    // The provider's new context becomes the parent context of
+    // mFrame's context.
+    parentContext = providerFrame->StyleContext();
+    // Set |mResolvedChild| so we don't bother resolving the
+    // provider again.
+    mResolvedChild = providerFrame;
+  }
 
-    if (content && content->IsElement()) {
-      content->OwnerDoc()->FlushPendingLinkUpdates();
-      RestyleTracker::RestyleData restyleData;
-      if (aRestyleTracker.GetRestyleData(content->AsElement(), &restyleData)) {
-        if (NS_UpdateHint(aMinChange, restyleData.mChangeHint)) {
-          aChangeList->AppendChange(aFrame, content, restyleData.mChangeHint);
-        }
-        aRestyleHint = nsRestyleHint(aRestyleHint | restyleData.mRestyleHint);
+  if (providerFrame != mFrame->GetParent()) {
+    // We don't actually know what the parent style context's
+    // non-inherited hints were, so assume the worst.
+    mParentFrameHintsNotHandledForDescendants =
+      nsChangeHint_Hints_NotHandledForDescendants;
+  }
+
+#ifdef DEBUG
+  {
+    // Check that our assumption that continuations of the same
+    // pseudo-type and with the same style context parent have the
+    // same style context is valid before the reresolution.  (We need
+    // to check the pseudo-type and style context parent because of
+    // :first-letter and :first-line, where we create styled and
+    // unstyled letter/line frames distinguished by pseudo-type, and
+    // then need to distinguish their descendants based on having
+    // different parents.)
+    nsIFrame *nextContinuation = mFrame->GetNextContinuation();
+    if (nextContinuation) {
+      nsStyleContext *nextContinuationContext =
+        nextContinuation->StyleContext();
+      NS_ASSERTION(oldContext == nextContinuationContext ||
+                   oldContext->GetPseudo() !=
+                     nextContinuationContext->GetPseudo() ||
+                   oldContext->GetParent() !=
+                     nextContinuationContext->GetParent(),
+                   "continuations should have the same style context");
+    }
+    // And assert the same thing for {ib} splits.  See the comments in
+    // GetPrevContinuationWithPossiblySameStyle for an explanation of
+    // why we step two forward in the special sibling chain.
+    if ((mFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
+        !mFrame->GetPrevContinuation()) {
+      nsIFrame *nextIBSibling = static_cast<nsIFrame*>(
+        mFrame->Properties().Get(nsIFrame::IBSplitSpecialSibling()));
+      if (nextIBSibling) {
+        nextIBSibling = static_cast<nsIFrame*>(
+          nextIBSibling->Properties().Get(nsIFrame::IBSplitSpecialSibling()));
+      }
+      if (nextIBSibling) {
+        nsStyleContext *nextIBSiblingContext =
+          nextIBSibling->StyleContext();
+        NS_ASSERTION(oldContext == nextIBSiblingContext ||
+                     oldContext->GetPseudo() !=
+                       nextIBSiblingContext->GetPseudo() ||
+                     oldContext->GetParent() !=
+                       nextIBSiblingContext->GetParent(),
+                     "continuations should have the same style context");
       }
     }
-
-    nsRestyleHint childRestyleHint = aRestyleHint;
-
-    if (childRestyleHint == eRestyle_Self) {
-      childRestyleHint = nsRestyleHint(0);
-    }
+  }
+#endif
 
-    nsStyleContext* parentContext;
-    nsIFrame* resolvedChild = nullptr;
-    // Get the frame providing the parent style context.  If it is a
-    // child, then resolve the provider first.
-    nsIFrame* providerFrame = aFrame->GetParentStyleContextFrame();
-    bool isChild = providerFrame && providerFrame->GetParent() == aFrame;
-    if (!isChild) {
-      if (providerFrame)
-        parentContext = providerFrame->StyleContext();
-      else
-        parentContext = nullptr;
+  // do primary context
+  nsRefPtr<nsStyleContext> newContext;
+  nsIFrame *prevContinuation =
+    GetPrevContinuationWithPossiblySameStyle(mFrame);
+  nsStyleContext *prevContinuationContext;
+  bool copyFromContinuation =
+    prevContinuation &&
+    (prevContinuationContext = prevContinuation->StyleContext())
+      ->GetPseudo() == oldContext->GetPseudo() &&
+     prevContinuationContext->GetParent() == parentContext;
+  if (copyFromContinuation) {
+    // Just use the style context from the frame's previous
+    // continuation (see assertion about mFrame->GetNextContinuation()
+    // above, which we would have previously hit for mFrame's previous
+    // continuation).
+    newContext = prevContinuationContext;
+  }
+  else if (pseudoTag == nsCSSAnonBoxes::mozNonElement) {
+    NS_ASSERTION(mFrame->GetContent(),
+                 "non pseudo-element frame without content node");
+    newContext = styleSet->ResolveStyleForNonElement(parentContext);
+  }
+  else if (!aRestyleHint && !prevContinuation) {
+    // Unfortunately, if prevContinuation is non-null then we may have
+    // already stolen the restyle tracker entry for this element while
+    // processing prevContinuation.  So we don't know whether aRestyleHint
+    // should really be 0 here or whether it should be eRestyle_Self.  Be
+    // pessimistic and force an actual reresolve in that situation.  The good
+    // news is that in the common case when prevContinuation is non-null we
+    // just used prevContinuationContext anyway and aren't reaching this code
+    // to start with.
+    newContext =
+      styleSet->ReparentStyleContext(oldContext, parentContext,
+                                     ElementForStyleContext(mParentContent,
+                                                            mFrame,
+                                                            pseudoType));
+  } else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
+    newContext = styleSet->ResolveAnonymousBoxStyle(pseudoTag,
+                                                    parentContext);
+  }
+  else {
+    Element* element = ElementForStyleContext(mParentContent,
+                                              mFrame,
+                                              pseudoType);
+    if (pseudoTag) {
+      if (pseudoTag == nsCSSPseudoElements::before ||
+          pseudoTag == nsCSSPseudoElements::after) {
+        // XXX what other pseudos do we need to treat like this?
+        newContext = styleSet->ProbePseudoElementStyle(element,
+                                                       pseudoType,
+                                                       parentContext,
+                                                       mTreeMatchContext);
+        if (!newContext) {
+          // This pseudo should no longer exist; gotta reframe
+          NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
+          mChangeList->AppendChange(mFrame, element,
+                                    nsChangeHint_ReconstructFrame);
+          // We're reframing anyway; just keep the same context
+          newContext = oldContext;
+        }
+      } else {
+        // Don't expect XUL tree stuff here, since it needs a comparator and
+        // all.
+        NS_ASSERTION(pseudoType <
+                       nsCSSPseudoElements::ePseudo_PseudoElementCount,
+                     "Unexpected pseudo type");
+        newContext = styleSet->ResolvePseudoElementStyle(element,
+                                                         pseudoType,
+                                                         parentContext);
+      }
     }
     else {
-      MOZ_ASSERT(providerFrame->GetContent() == aFrame->GetContent(),
-                 "Postcondition for GetParentStyleContextFrame() violated. "
-                 "That means we need to add the current element to the "
-                 "ancestor filter.");
-
-      // resolve the provider here (before aFrame below).
+      NS_ASSERTION(mFrame->GetContent(),
+                   "non pseudo-element frame without content node");
+      // Skip flex-item style fixup for anonymous subtrees:
+      TreeMatchContext::AutoFlexItemStyleFixupSkipper
+        flexFixupSkipper(mTreeMatchContext,
+                         element->IsRootOfNativeAnonymousSubtree());
+      newContext = styleSet->ResolveStyleFor(element, parentContext,
+                                             mTreeMatchContext);
+    }
+  }
 
-      // assumeDifferenceHint forces the parent's change to be also
-      // applied to this frame, no matter what
-      // nsStyleContext::CalcStyleDifference says. CalcStyleDifference
-      // can't be trusted because it assumes any changes to the parent
-      // style context provider will be automatically propagated to
-      // the frame(s) with child style contexts.
+  if (!newContext) {
+    NS_RUNTIMEABORT("couldn't allocate new style context");
+  }
 
-      assumeDifferenceHint = ReResolveStyleContext(aPresContext, providerFrame,
-                                                   aParentContent, aChangeList,
-                                                   aMinChange,
-                                                   nsChangeHint_Hints_NotHandledForDescendants,
-                                                   aRestyleHint,
-                                                   aRestyleTracker,
-                                                   aDesiredA11yNotifications,
-                                                   aVisibleKidsOfHiddenElement,
-                                                   aTreeMatchContext);
+  if (!parentContext) {
+    if (oldContext->RuleNode() == newContext->RuleNode() &&
+        oldContext->IsLinkContext() == newContext->IsLinkContext() &&
+        oldContext->RelevantLinkVisited() ==
+          newContext->RelevantLinkVisited()) {
+      // We're the root of the style context tree and the new style
+      // context returned has the same rule node.  This means that
+      // we can use FindChildWithRules to keep a lot of the old
+      // style contexts around.  However, we need to start from the
+      // same root.
+      newContext = oldContext;
+    }
+  }
 
-      // The provider's new context becomes the parent context of
-      // aFrame's context.
-      parentContext = providerFrame->StyleContext();
-      // Set |resolvedChild| so we don't bother resolving the
-      // provider again.
-      resolvedChild = providerFrame;
-    }
-
-    if (providerFrame != aFrame->GetParent()) {
-      // We don't actually know what the parent style context's
-      // non-inherited hints were, so assume the worst.
-      aParentFrameHintsNotHandledForDescendants =
-        nsChangeHint_Hints_NotHandledForDescendants;
+  if (newContext != oldContext) {
+    if (!copyFromContinuation) {
+      TryStartingTransition(mPresContext, mFrame->GetContent(),
+                            oldContext, &newContext);
     }
 
-#ifdef DEBUG
-    {
-      // Check that our assumption that continuations of the same
-      // pseudo-type and with the same style context parent have the
-      // same style context is valid before the reresolution.  (We need
-      // to check the pseudo-type and style context parent because of
-      // :first-letter and :first-line, where we create styled and
-      // unstyled letter/line frames distinguished by pseudo-type, and
-      // then need to distinguish their descendants based on having
-      // different parents.)
-      nsIFrame *nextContinuation = aFrame->GetNextContinuation();
-      if (nextContinuation) {
-        nsStyleContext *nextContinuationContext =
-          nextContinuation->StyleContext();
-        NS_ASSERTION(oldContext == nextContinuationContext ||
-                     oldContext->GetPseudo() !=
-                       nextContinuationContext->GetPseudo() ||
-                     oldContext->GetParent() !=
-                       nextContinuationContext->GetParent(),
-                     "continuations should have the same style context");
-      }
-      // And assert the same thing for {ib} splits.  See the comments in
-      // GetPrevContinuationWithPossiblySameStyle for an explanation of
-      // why we step two forward in the special sibling chain.
-      if ((aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
-          !aFrame->GetPrevContinuation()) {
-        nsIFrame *nextIBSibling = static_cast<nsIFrame*>(
-          aFrame->Properties().Get(nsIFrame::IBSplitSpecialSibling()));
-        if (nextIBSibling) {
-          nextIBSibling = static_cast<nsIFrame*>(
-            nextIBSibling->Properties().Get(nsIFrame::IBSplitSpecialSibling()));
-        }
-        if (nextIBSibling) {
-          nsStyleContext *nextIBSiblingContext =
-            nextIBSibling->StyleContext();
-          NS_ASSERTION(oldContext == nextIBSiblingContext ||
-                       oldContext->GetPseudo() !=
-                         nextIBSiblingContext->GetPseudo() ||
-                       oldContext->GetParent() !=
-                         nextIBSiblingContext->GetParent(),
-                       "continuations should have the same style context");
+    CaptureChange(oldContext, newContext, assumeDifferenceHint);
+    if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
+      // if frame gets regenerated, let it keep old context
+      mFrame->SetStyleContext(newContext);
+    }
+  }
+  oldContext = nullptr;
+
+  // do additional contexts
+  // XXXbz might be able to avoid selector matching here in some
+  // cases; won't worry about it for now.
+  int32_t contextIndex = 0;
+  for (nsStyleContext* oldExtraContext;
+       (oldExtraContext = mFrame->GetAdditionalStyleContext(contextIndex));
+       ++contextIndex) {
+    nsRefPtr<nsStyleContext> newExtraContext;
+    nsIAtom* const extraPseudoTag = oldExtraContext->GetPseudo();
+    const nsCSSPseudoElements::Type extraPseudoType =
+      oldExtraContext->GetPseudoType();
+    NS_ASSERTION(extraPseudoTag &&
+                 extraPseudoTag != nsCSSAnonBoxes::mozNonElement,
+                 "extra style context is not pseudo element");
+    if (extraPseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
+      newExtraContext = styleSet->ResolveAnonymousBoxStyle(extraPseudoTag,
+                                                           newContext);
+    }
+    else {
+      // Don't expect XUL tree stuff here, since it needs a comparator and
+      // all.
+      NS_ASSERTION(extraPseudoType <
+                     nsCSSPseudoElements::ePseudo_PseudoElementCount,
+                   "Unexpected type");
+      newExtraContext = styleSet->ResolvePseudoElementStyle(mContent->AsElement(),
+                                                            extraPseudoType,
+                                                            newContext);
+    }
+    if (newExtraContext) {
+      if (oldExtraContext != newExtraContext) {
+        CaptureChange(oldExtraContext, newExtraContext, assumeDifferenceHint);
+        if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
+          mFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
         }
       }
     }
-#endif
+  }
+}
+
+void
+ElementRestyler::RestyleChildren(nsRestyleHint aChildRestyleHint)
+{
+  RestyleUndisplayedChildren(aChildRestyleHint);
+
+  // Check whether we might need to create a new ::before frame.
+  // There's no need to do this if we're planning to reframe already
+  // or if we're not forcing restyles on kids.
+  // It's also important to check mHintsHandled since we use
+  // mFrame->StyleContext(), which is out of date if mHintsHandled has a
+  // ReconstructFrame hint.  Using an out of date style context could
+  // trigger assertions about mismatched rule trees.
+  if (!(mHintsHandled & nsChangeHint_ReconstructFrame) &&
+      aChildRestyleHint) {
+    RestyleBeforePseudo();
+  }
+
+  // Check whether we might need to create a new ::after frame.
+  // See comments above regarding :before.
+  if (!(mHintsHandled & nsChangeHint_ReconstructFrame) &&
+      aChildRestyleHint) {
+    RestyleAfterPseudo();
+  }
+
+  // There is no need to waste time crawling into a frame's children
+  // on a frame change.  The act of reconstructing frames will force
+  // new style contexts to be resolved on all of this frame's
+  // descendants anyway, so we want to avoid wasting time processing
+  // style contexts that we're just going to throw away anyway. - dwh
+  // It's also important to check mHintsHandled since reresolving the
+  // kids would use mFrame->StyleContext(), which is out of date if
+  // mHintsHandled has a ReconstructFrame hint; doing this could trigger
+  // assertions about mismatched rule trees.
+  if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
+    InitializeAccessibilityNotifications();
+
+    RestyleContentChildren(aChildRestyleHint);
+
+    SendAccessibilityNotifications();
+  }
+}
 
-    // do primary context
-    nsRefPtr<nsStyleContext> newContext;
-    nsChangeHint nonInheritedHints = nsChangeHint(0);
-    nsIFrame *prevContinuation =
-      GetPrevContinuationWithPossiblySameStyle(aFrame);
-    nsStyleContext *prevContinuationContext;
-    bool copyFromContinuation =
-      prevContinuation &&
-      (prevContinuationContext = prevContinuation->StyleContext())
-        ->GetPseudo() == oldContext->GetPseudo() &&
-       prevContinuationContext->GetParent() == parentContext;
-    if (copyFromContinuation) {
-      // Just use the style context from the frame's previous
-      // continuation (see assertion about aFrame->GetNextContinuation()
-      // above, which we would have previously hit for aFrame's previous
-      // continuation).
-      newContext = prevContinuationContext;
-    }
-    else if (pseudoTag == nsCSSAnonBoxes::mozNonElement) {
-      NS_ASSERTION(localContent,
-                   "non pseudo-element frame without content node");
-      newContext = styleSet->ResolveStyleForNonElement(parentContext);
-    }
-    else if (!aRestyleHint && !prevContinuation) {
-      // Unfortunately, if prevContinuation is non-null then we may have
-      // already stolen the restyle tracker entry for this element while
-      // processing prevContinuation.  So we don't know whether aRestyleHint
-      // should really be 0 here or whether it should be eRestyle_Self.  Be
-      // pessimistic and force an actual reresolve in that situation.  The good
-      // news is that in the common case when prevContinuation is non-null we
-      // just used prevContinuationContext anyway and aren't reaching this code
-      // to start with.
-      newContext =
-        styleSet->ReparentStyleContext(oldContext, parentContext,
-                                       ElementForStyleContext(aParentContent,
-                                                              aFrame,
-                                                              pseudoType));
-    } else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
-      newContext = styleSet->ResolveAnonymousBoxStyle(pseudoTag,
-                                                      parentContext);
-    }
-    else {
-      Element* element = ElementForStyleContext(aParentContent,
-                                                aFrame,
-                                                pseudoType);
-      if (pseudoTag) {
-        if (pseudoTag == nsCSSPseudoElements::before ||
-            pseudoTag == nsCSSPseudoElements::after) {
-          // XXX what other pseudos do we need to treat like this?
-          newContext = styleSet->ProbePseudoElementStyle(element,
-                                                         pseudoType,
-                                                         parentContext,
-                                                         aTreeMatchContext);
-          if (!newContext) {
-            // This pseudo should no longer exist; gotta reframe
-            NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame);
-            aChangeList->AppendChange(aFrame, element,
-                                      nsChangeHint_ReconstructFrame);
-            // We're reframing anyway; just keep the same context
-            newContext = oldContext;
-          }
+void
+ElementRestyler::RestyleUndisplayedChildren(nsRestyleHint aChildRestyleHint)
+{
+  // When the root element is display:none, we still construct *some*
+  // frames that have the root element as their mContent, down to the
+  // DocElementContainingBlock.
+  bool checkUndisplayed;
+  nsIContent* undisplayedParent;
+  nsCSSFrameConstructor* frameConstructor = mPresContext->FrameConstructor();
+  if (mFrame->StyleContext()->GetPseudo()) {
+    checkUndisplayed = mFrame == frameConstructor->
+                                   GetDocElementContainingBlock();
+    undisplayedParent = nullptr;
+  } else {
+    checkUndisplayed = !!mFrame->GetContent();
+    undisplayedParent = mFrame->GetContent();
+  }
+  if (checkUndisplayed &&
+      // No need to do this if we're planning to reframe already.
+      // It's also important to check mHintsHandled since we use
+      // mFrame->StyleContext(), which is out of date if mHintsHandled
+      // has a ReconstructFrame hint.  Using an out of date style
+      // context could trigger assertions about mismatched rule trees.
+      !(mHintsHandled & nsChangeHint_ReconstructFrame)) {
+    UndisplayedNode* undisplayed =
+      frameConstructor->GetAllUndisplayedContentIn(undisplayedParent);
+    for (TreeMatchContext::AutoAncestorPusher
+           pushAncestor(undisplayed, mTreeMatchContext,
+                        undisplayedParent ? undisplayedParent->AsElement()
+                                          : nullptr);
+         undisplayed; undisplayed = undisplayed->mNext) {
+      NS_ASSERTION(undisplayedParent ||
+                   undisplayed->mContent ==
+                     mPresContext->Document()->GetRootElement(),
+                   "undisplayed node child of null must be root");
+      NS_ASSERTION(!undisplayed->mStyle->GetPseudo(),
+                   "Shouldn't have random pseudo style contexts in the "
+                   "undisplayed map");
+
+      // Get the parent of the undisplayed content and check if it is a XBL
+      // children element. Push the children element as an ancestor here because it does
+      // not have a frame and would not otherwise be pushed as an ancestor.
+      nsIContent* parent = undisplayed->mContent->GetParent();
+      bool pushInsertionPoint = parent && parent->IsActiveChildrenElement();
+      TreeMatchContext::AutoAncestorPusher
+        insertionPointPusher(pushInsertionPoint,
+                             mTreeMatchContext,
+                             parent && parent->IsElement() ? parent->AsElement() : nullptr);
+
+      nsRestyleHint thisChildHint = aChildRestyleHint;
+      RestyleTracker::RestyleData undisplayedRestyleData;
+      if (mRestyleTracker.GetRestyleData(undisplayed->mContent->AsElement(),
+                                         &undisplayedRestyleData)) {
+        thisChildHint =
+          nsRestyleHint(thisChildHint | undisplayedRestyleData.mRestyleHint);
+      }
+      nsRefPtr<nsStyleContext> undisplayedContext;
+      nsStyleSet* styleSet = mPresContext->StyleSet();
+      if (thisChildHint) {
+        undisplayedContext =
+          styleSet->ResolveStyleFor(undisplayed->mContent->AsElement(),
+                                    mFrame->StyleContext(),
+                                    mTreeMatchContext);
+      } else {
+        undisplayedContext =
+          styleSet->ReparentStyleContext(undisplayed->mStyle,
+                                         mFrame->StyleContext(),
+                                         undisplayed->mContent->AsElement());
+      }
+      if (undisplayedContext) {
+        const nsStyleDisplay* display = undisplayedContext->StyleDisplay();
+        if (display->mDisplay != NS_STYLE_DISPLAY_NONE) {
+          NS_ASSERTION(undisplayed->mContent,
+                       "Must have undisplayed content");
+          mChangeList->AppendChange(nullptr, undisplayed->mContent,
+                                    NS_STYLE_HINT_FRAMECHANGE);
+          // The node should be removed from the undisplayed map when
+          // we reframe it.
         } else {
-          // Don't expect XUL tree stuff here, since it needs a comparator and
-          // all.
-          NS_ASSERTION(pseudoType <
-                         nsCSSPseudoElements::ePseudo_PseudoElementCount,
-                       "Unexpected pseudo type");
-          newContext = styleSet->ResolvePseudoElementStyle(element,
-                                                           pseudoType,
-                                                           parentContext);
-        }
-      }
-      else {
-        NS_ASSERTION(localContent,
-                     "non pseudo-element frame without content node");
-        // Skip flex-item style fixup for anonymous subtrees:
-        TreeMatchContext::AutoFlexItemStyleFixupSkipper
-          flexFixupSkipper(aTreeMatchContext,
-                           element->IsRootOfNativeAnonymousSubtree());
-        newContext = styleSet->ResolveStyleFor(element, parentContext,
-                                               aTreeMatchContext);
-      }
-    }
-
-    NS_ASSERTION(newContext, "failed to get new style context");
-    if (newContext) {
-      if (!parentContext) {
-        if (oldContext->RuleNode() == newContext->RuleNode() &&
-            oldContext->IsLinkContext() == newContext->IsLinkContext() &&
-            oldContext->RelevantLinkVisited() ==
-              newContext->RelevantLinkVisited()) {
-          // We're the root of the style context tree and the new style
-          // context returned has the same rule node.  This means that
-          // we can use FindChildWithRules to keep a lot of the old
-          // style contexts around.  However, we need to start from the
-          // same root.
-          newContext = oldContext;
-        }
-      }
-
-      if (newContext != oldContext) {
-        if (!copyFromContinuation) {
-          TryStartingTransition(aPresContext, aFrame->GetContent(),
-                                oldContext, &newContext);
-        }
-
-        CaptureChange(oldContext, newContext, aFrame, content, aChangeList,
-                      aMinChange, aParentFrameHintsNotHandledForDescendants,
-                      nonInheritedHints, assumeDifferenceHint);
-        if (!(aMinChange & nsChangeHint_ReconstructFrame)) {
-          // if frame gets regenerated, let it keep old context
-          aFrame->SetStyleContext(newContext);
+          // update the undisplayed node with the new context
+          undisplayed->mStyle = undisplayedContext;
         }
       }
-      oldContext->Release();
     }
-    else {
-      NS_ERROR("resolve style context failed");
-      newContext = oldContext;  // new context failed, recover...
-    }
+  }
+}
 
-    // do additional contexts
-    // XXXbz might be able to avoid selector matching here in some
-    // cases; won't worry about it for now.
-    int32_t contextIndex = -1;
-    while (1 == 1) {
-      nsStyleContext* oldExtraContext = nullptr;
-      oldExtraContext = aFrame->GetAdditionalStyleContext(++contextIndex);
-      if (oldExtraContext) {
-        nsRefPtr<nsStyleContext> newExtraContext;
-        nsIAtom* const extraPseudoTag = oldExtraContext->GetPseudo();
-        const nsCSSPseudoElements::Type extraPseudoType =
-          oldExtraContext->GetPseudoType();
-        NS_ASSERTION(extraPseudoTag &&
-                     extraPseudoTag != nsCSSAnonBoxes::mozNonElement,
-                     "extra style context is not pseudo element");
-        if (extraPseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
-          newExtraContext = styleSet->ResolveAnonymousBoxStyle(extraPseudoTag,
-                                                               newContext);
-        }
-        else {
-          // Don't expect XUL tree stuff here, since it needs a comparator and
-          // all.
-          NS_ASSERTION(extraPseudoType <
-                         nsCSSPseudoElements::ePseudo_PseudoElementCount,
-                       "Unexpected type");
-          newExtraContext = styleSet->ResolvePseudoElementStyle(content->AsElement(),
-                                                                extraPseudoType,
-                                                                newContext);
-        }
-        if (newExtraContext) {
-          if (oldExtraContext != newExtraContext) {
-            nsChangeHint extraHintsNotHandledForDescendants = nsChangeHint(0);
-            CaptureChange(oldExtraContext, newExtraContext, aFrame, content,
-                          aChangeList, aMinChange,
-                          aParentFrameHintsNotHandledForDescendants,
-                          extraHintsNotHandledForDescendants,
-                          assumeDifferenceHint);
-            NS_UpdateHint(nonInheritedHints, extraHintsNotHandledForDescendants);
-            if (!(aMinChange & nsChangeHint_ReconstructFrame)) {
-              aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
-            }
-          }
-        }
+void
+ElementRestyler::RestyleBeforePseudo()
+{
+  // Make sure not to do this for pseudo-frames or frames that
+  // can't have generated content.
+  if (!mFrame->StyleContext()->GetPseudo() &&
+      ((mFrame->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT) ||
+       // Our content insertion frame might have gotten flagged
+       (mFrame->GetContentInsertionFrame()->GetStateBits() &
+        NS_FRAME_MAY_HAVE_GENERATED_CONTENT))) {
+    // Check for a new :before pseudo and an existing :before
+    // frame, but only if the frame is the first continuation.
+    nsIFrame* prevContinuation = mFrame->GetPrevContinuation();
+    if (!prevContinuation) {
+      // Checking for a :before frame is cheaper than getting the
+      // :before style context.
+      if (!nsLayoutUtils::GetBeforeFrame(mFrame) &&
+          nsLayoutUtils::HasPseudoStyle(mFrame->GetContent(),
+                                        mFrame->StyleContext(),
+                                        nsCSSPseudoElements::ePseudo_before,
+                                        mPresContext)) {
+        // Have to create the new :before frame
+        NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
+        mChangeList->AppendChange(mFrame, mContent,
+                                  nsChangeHint_ReconstructFrame);
       }
-      else {
-        break;
+    }
+  }
+}
+
+void
+ElementRestyler::RestyleAfterPseudo()
+{
+  // Make sure not to do this for pseudo-frames or frames that
+  // can't have generated content.
+  if (!mFrame->StyleContext()->GetPseudo() &&
+      ((mFrame->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT) ||
+       // Our content insertion frame might have gotten flagged
+       (mFrame->GetContentInsertionFrame()->GetStateBits() &
+        NS_FRAME_MAY_HAVE_GENERATED_CONTENT))) {
+    // Check for new :after content, but only if the frame is the
+    // last continuation.
+    nsIFrame* nextContinuation = mFrame->GetNextContinuation();
+
+    if (!nextContinuation) {
+      // Getting the :after frame is more expensive than getting the pseudo
+      // context, so get the pseudo context first.
+      if (nsLayoutUtils::HasPseudoStyle(mFrame->GetContent(),
+                                        mFrame->StyleContext(),
+                                        nsCSSPseudoElements::ePseudo_after,
+                                        mPresContext) &&
+          !nsLayoutUtils::GetAfterFrame(mFrame)) {
+        // have to create the new :after frame
+        NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
+        mChangeList->AppendChange(mFrame, mContent,
+                                  nsChangeHint_ReconstructFrame);
       }
     }
-
-    // now look for undisplayed child content and pseudos
+  }
+}
 
-    // When the root element is display:none, we still construct *some*
-    // frames that have the root element as their mContent, down to the
-    // DocElementContainingBlock.
-    bool checkUndisplayed;
-    nsIContent* undisplayedParent;
-    nsCSSFrameConstructor* frameConstructor = FrameConstructor();
-    if (pseudoTag) {
-      checkUndisplayed = aFrame == frameConstructor->
-                                     GetDocElementContainingBlock();
-      undisplayedParent = nullptr;
-    } else {
-      checkUndisplayed = !!localContent;
-      undisplayedParent = localContent;
+void
+ElementRestyler::InitializeAccessibilityNotifications()
+{
+#ifdef ACCESSIBILITY
+  // Notify a11y for primary frame only if it's a root frame of visibility
+  // changes or its parent frame was hidden while it stays visible and
+  // it is not inside a {ib} split or is the first frame of {ib} split.
+  if (nsIPresShell::IsAccessibilityActive() &&
+      !mFrame->GetPrevContinuation() &&
+      !nsLayoutUtils::FrameIsNonFirstInIBSplit(mFrame)) {
+    if (mDesiredA11yNotifications == eSendAllNotifications) {
+      bool isFrameVisible = mFrame->StyleVisibility()->IsVisible();
+      if (isFrameVisible != mWasFrameVisible) {
+        if (isFrameVisible) {
+          // Notify a11y the element (perhaps with its children) was shown.
+          // We don't fall into this case if this element gets or stays shown
+          // while its parent becomes hidden.
+          mKidsDesiredA11yNotifications = eSkipNotifications;
+          mOurA11yNotification = eNotifyShown;
+        } else {
+          // The element is being hidden; its children may stay visible, or
+          // become visible after being hidden previously. If we'll find
+          // visible children then we should notify a11y about that as if
+          // they were inserted into tree. Notify a11y this element was
+          // hidden.
+          mKidsDesiredA11yNotifications = eNotifyIfShown;
+          mOurA11yNotification = eNotifyHidden;
+        }
+      }
+    } else if (mDesiredA11yNotifications == eNotifyIfShown &&
+               mFrame->StyleVisibility()->IsVisible()) {
+      // Notify a11y that element stayed visible while its parent was
+      // hidden.
+      mVisibleKidsOfHiddenElement.AppendElement(mFrame->GetContent());
+      mKidsDesiredA11yNotifications = eSkipNotifications;
     }
-    if (checkUndisplayed) {
-      UndisplayedNode* undisplayed =
-        frameConstructor->GetAllUndisplayedContentIn(undisplayedParent);
-      for (TreeMatchContext::AutoAncestorPusher
-             pushAncestor(undisplayed, aTreeMatchContext,
-                          undisplayedParent ? undisplayedParent->AsElement()
-                                            : nullptr);
-           undisplayed; undisplayed = undisplayed->mNext) {
-        NS_ASSERTION(undisplayedParent ||
-                     undisplayed->mContent ==
-                       mPresContext->Document()->GetRootElement(),
-                     "undisplayed node child of null must be root");
-        NS_ASSERTION(!undisplayed->mStyle->GetPseudo(),
-                     "Shouldn't have random pseudo style contexts in the "
-                     "undisplayed map");
+  }
+#endif
+}
 
-        // Get the parent of the undisplayed content and check if it is a XBL
-        // children element. Push the children element as an ancestor here because it does
-        // not have a frame and would not otherwise be pushed as an ancestor.
-        nsIContent* parent = undisplayed->mContent->GetParent();
+void
+ElementRestyler::RestyleContentChildren(nsRestyleHint aChildRestyleHint)
+{
+  nsIFrame::ChildListIterator lists(mFrame);
+  for (TreeMatchContext::AutoAncestorPusher
+         pushAncestor(!lists.IsDone(),
+                      mTreeMatchContext,
+                      mContent && mContent->IsElement()
+                        ? mContent->AsElement() : nullptr);
+       !lists.IsDone(); lists.Next()) {
+    nsFrameList::Enumerator childFrames(lists.CurrentList());
+    for (; !childFrames.AtEnd(); childFrames.Next()) {
+      nsIFrame* child = childFrames.get();
+      if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
+        // Get the parent of the child frame's content and check if it
+        // is a XBL children element. Push the children element as an
+        // ancestor here because it does not have a frame and would not
+        // otherwise be pushed as an ancestor.
+
+        // Check if the frame has a content because |child| may be a
+        // nsPageFrame that does not have a content.
+        nsIContent* parent = child->GetContent() ? child->GetContent()->GetParent() : nullptr;
         bool pushInsertionPoint = parent && parent->IsActiveChildrenElement();
         TreeMatchContext::AutoAncestorPusher
-          insertionPointPusher(pushInsertionPoint,
-                               aTreeMatchContext,
+          insertionPointPusher(pushInsertionPoint, mTreeMatchContext,
                                parent && parent->IsElement() ? parent->AsElement() : nullptr);
 
-        nsRestyleHint thisChildHint = childRestyleHint;
-        RestyleTracker::RestyleData undisplayedRestyleData;
-        if (aRestyleTracker.GetRestyleData(undisplayed->mContent->AsElement(),
-                                           &undisplayedRestyleData)) {
-          thisChildHint =
-            nsRestyleHint(thisChildHint | undisplayedRestyleData.mRestyleHint);
+        // only do frames that are in flow
+        if (nsGkAtoms::placeholderFrame == child->GetType()) { // placeholder
+          // get out of flow frame and recur there
+          nsIFrame* outOfFlowFrame =
+            nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
+          NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
+          NS_ASSERTION(outOfFlowFrame != mResolvedChild,
+                       "out-of-flow frame not a true descendant");
+
+          // Note that the out-of-flow may not be a geometric descendant of
+          // the frame where we started the reresolve.  Therefore, even if
+          // mHintsHandled already includes nsChangeHint_AllReflowHints we don't
+          // want to pass that on to the out-of-flow reresolve, since that
+          // can lead to the out-of-flow not getting reflowed when it should
+          // be (eg a reresolve starting at <body> that involves reflowing
+          // the <body> would miss reflowing fixed-pos nodes that also need
+          // reflow).  In the cases when the out-of-flow _is_ a geometric
+          // descendant of a frame we already have a reflow hint for,
+          // reflow coalescing should keep us from doing the work twice.
+
+          // |nsFrame::GetParentStyleContextFrame| checks being out
+          // of flow so that this works correctly.
+          do {
+            ElementRestyler oofRestyler(*this, outOfFlowFrame,
+                                        FOR_OUT_OF_FLOW_CHILD);
+            oofRestyler.Restyle(aChildRestyleHint);
+          } while ((outOfFlowFrame = outOfFlowFrame->GetNextContinuation()));
+
+          // reresolve placeholder's context under the same parent
+          // as the out-of-flow frame
+          ElementRestyler phRestyler(*this, child, 0);
+          phRestyler.Restyle(aChildRestyleHint);
         }
-        nsRefPtr<nsStyleContext> undisplayedContext;
-        if (thisChildHint) {
-          undisplayedContext =
-            styleSet->ResolveStyleFor(undisplayed->mContent->AsElement(),
-                                      newContext,
-                                      aTreeMatchContext);
-        } else {
-          undisplayedContext =
-            styleSet->ReparentStyleContext(undisplayed->mStyle, newContext,
-                                           undisplayed->mContent->AsElement());
-        }
-        if (undisplayedContext) {
-          const nsStyleDisplay* display = undisplayedContext->StyleDisplay();
-          if (display->mDisplay != NS_STYLE_DISPLAY_NONE) {
-            NS_ASSERTION(undisplayed->mContent,
-                         "Must have undisplayed content");
-            aChangeList->AppendChange(nullptr, undisplayed->mContent,
-                                      NS_STYLE_HINT_FRAMECHANGE);
-            // The node should be removed from the undisplayed map when
-            // we reframe it.
-          } else {
-            // update the undisplayed node with the new context
-            undisplayed->mStyle = undisplayedContext;
+        else {  // regular child frame
+          if (child != mResolvedChild) {
+            ElementRestyler childRestyler(*this, child, 0);
+            childRestyler.Restyle(aChildRestyleHint);
           }
         }
       }
     }
-
-    // Check whether we might need to create a new ::before frame.
-    // There's no need to do this if we're planning to reframe already
-    // or if we're not forcing restyles on kids.
-    if (!(aMinChange & nsChangeHint_ReconstructFrame) &&
-        childRestyleHint) {
-      // Make sure not to do this for pseudo-frames or frames that
-      // can't have generated content.
-      if (!pseudoTag &&
-          ((aFrame->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT) ||
-           // Our content insertion frame might have gotten flagged
-           (aFrame->GetContentInsertionFrame()->GetStateBits() &
-            NS_FRAME_MAY_HAVE_GENERATED_CONTENT))) {
-        // Check for a new :before pseudo and an existing :before
-        // frame, but only if the frame is the first continuation.
-        nsIFrame* prevContinuation = aFrame->GetPrevContinuation();
-        if (!prevContinuation) {
-          // Checking for a :before frame is cheaper than getting the
-          // :before style context.
-          if (!nsLayoutUtils::GetBeforeFrame(aFrame) &&
-              nsLayoutUtils::HasPseudoStyle(localContent, newContext,
-                                            nsCSSPseudoElements::ePseudo_before,
-                                            aPresContext)) {
-            // Have to create the new :before frame
-            NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame);
-            aChangeList->AppendChange(aFrame, content,
-                                      nsChangeHint_ReconstructFrame);
-          }
-        }
-      }
-    }
-
-    // Check whether we might need to create a new ::after frame.
-    // There's no need to do this if we're planning to reframe already
-    // or if we're not forcing restyles on kids.
-    if (!(aMinChange & nsChangeHint_ReconstructFrame) &&
-        childRestyleHint) {
-      // Make sure not to do this for pseudo-frames or frames that
-      // can't have generated content.
-      if (!pseudoTag &&
-          ((aFrame->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT) ||
-           // Our content insertion frame might have gotten flagged
-           (aFrame->GetContentInsertionFrame()->GetStateBits() &
-            NS_FRAME_MAY_HAVE_GENERATED_CONTENT))) {
-        // Check for new :after content, but only if the frame is the
-        // last continuation.
-        nsIFrame* nextContinuation = aFrame->GetNextContinuation();
+  }
+  // XXX need to do overflow frames???
+}
 
-        if (!nextContinuation) {
-          // Getting the :after frame is more expensive than getting the pseudo
-          // context, so get the pseudo context first.
-          if (nsLayoutUtils::HasPseudoStyle(localContent, newContext,
-                                            nsCSSPseudoElements::ePseudo_after,
-                                            aPresContext) &&
-              !nsLayoutUtils::GetAfterFrame(aFrame)) {
-            // have to create the new :after frame
-            NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame);
-            aChangeList->AppendChange(aFrame, content,
-                                      nsChangeHint_ReconstructFrame);
-          }
-        }
-      }
-    }
-
-    // There is no need to waste time crawling into a frame's children
-    // on a frame change.  The act of reconstructing frames will force
-    // new style contexts to be resolved on all of this frame's
-    // descendants anyway, so we want to avoid wasting time processing
-    // style contexts that we're just going to throw away anyway. - dwh
-    if (!(aMinChange & nsChangeHint_ReconstructFrame)) {
-
-      DesiredA11yNotifications kidsDesiredA11yNotification =
-        aDesiredA11yNotifications;
+void
+ElementRestyler::SendAccessibilityNotifications()
+{
 #ifdef ACCESSIBILITY
-      A11yNotificationType ourA11yNotification = eDontNotify;
-      // Notify a11y for primary frame only if it's a root frame of visibility
-      // changes or its parent frame was hidden while it stays visible and
-      // it is not inside a {ib} split or is the first frame of {ib} split.
-      if (nsIPresShell::IsAccessibilityActive() &&
-          !aFrame->GetPrevContinuation() &&
-          !nsLayoutUtils::FrameIsNonFirstInIBSplit(aFrame)) {
-        if (aDesiredA11yNotifications == eSendAllNotifications) {
-          bool isFrameVisible = newContext->StyleVisibility()->IsVisible();
-          if (isFrameVisible != wasFrameVisible) {
-            if (isFrameVisible) {
-              // Notify a11y the element (perhaps with its children) was shown.
-              // We don't fall into this case if this element gets or stays shown
-              // while its parent becomes hidden.
-              kidsDesiredA11yNotification = eSkipNotifications;
-              ourA11yNotification = eNotifyShown;
-            } else {
-              // The element is being hidden; its children may stay visible, or
-              // become visible after being hidden previously. If we'll find
-              // visible children then we should notify a11y about that as if
-              // they were inserted into tree. Notify a11y this element was
-              // hidden.
-              kidsDesiredA11yNotification = eNotifyIfShown;
-              ourA11yNotification = eNotifyHidden;
-            }
-          }
-        } else if (aDesiredA11yNotifications == eNotifyIfShown &&
-                   newContext->StyleVisibility()->IsVisible()) {
-          // Notify a11y that element stayed visible while its parent was
-          // hidden.
-          aVisibleKidsOfHiddenElement.AppendElement(aFrame->GetContent());
-          kidsDesiredA11yNotification = eSkipNotifications;
-        }
-      }
-#endif
+  // Send notifications about visibility changes.
+  if (mOurA11yNotification == eNotifyShown) {
+    nsAccessibilityService* accService = nsIPresShell::AccService();
+    if (accService) {
+      nsIPresShell* presShell = mFrame->PresContext()->GetPresShell();
+      nsIContent* content = mFrame->GetContent();
 
-      // now do children
-      nsIFrame::ChildListIterator lists(aFrame);
-      for (TreeMatchContext::AutoAncestorPusher
-             pushAncestor(!lists.IsDone(),
-                          aTreeMatchContext,
-                          content && content->IsElement() ? content->AsElement()
-                                                          : nullptr);
-           !lists.IsDone(); lists.Next()) {
-        nsFrameList::Enumerator childFrames(lists.CurrentList());
-        for (; !childFrames.AtEnd(); childFrames.Next()) {
-          nsIFrame* child = childFrames.get();
-          if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
-            // Get the parent of the child frame's content and check if it is a XBL
-            // children element. Push the children element as an ancestor here because it does
-            // not have a frame and would not otherwise be pushed as an ancestor.
-
-            // Check if the frame has a content because |child| may be a nsPageFrame that does
-            // not have a content.
-            nsIContent* parent = child->GetContent() ? child->GetContent()->GetParent() : nullptr;
-            bool pushInsertionPoint = parent && parent->IsActiveChildrenElement();
-            TreeMatchContext::AutoAncestorPusher
-              insertionPointPusher(pushInsertionPoint, aTreeMatchContext,
-                                   parent && parent->IsElement() ? parent->AsElement() : nullptr);
-
-            // only do frames that are in flow
-            if (nsGkAtoms::placeholderFrame == child->GetType()) { // placeholder
-              // get out of flow frame and recur there
-              nsIFrame* outOfFlowFrame =
-                nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
-              NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
-              NS_ASSERTION(outOfFlowFrame != resolvedChild,
-                           "out-of-flow frame not a true descendant");
-
-              // Note that the out-of-flow may not be a geometric descendant of
-              // the frame where we started the reresolve.  Therefore, even if
-              // aMinChange already includes nsChangeHint_AllReflowHints we don't
-              // want to pass that on to the out-of-flow reresolve, since that
-              // can lead to the out-of-flow not getting reflowed when it should
-              // be (eg a reresolve starting at <body> that involves reflowing
-              // the <body> would miss reflowing fixed-pos nodes that also need
-              // reflow).  In the cases when the out-of-flow _is_ a geometric
-              // descendant of a frame we already have a reflow hint for,
-              // reflow coalescing should keep us from doing the work twice.
-
-              // |nsFrame::GetParentStyleContextFrame| checks being out
-              // of flow so that this works correctly.
-              do {
-                ReResolveStyleContext(aPresContext, outOfFlowFrame,
-                                      content, aChangeList,
-                                      NS_SubtractHint(aMinChange,
-                                                      nsChangeHint_AllReflowHints),
-                                      nonInheritedHints,
-                                      childRestyleHint,
-                                      aRestyleTracker,
-                                      kidsDesiredA11yNotification,
-                                      aVisibleKidsOfHiddenElement,
-                                      aTreeMatchContext);
-              } while ((outOfFlowFrame = outOfFlowFrame->GetNextContinuation()));
+      accService->ContentRangeInserted(presShell, content->GetParent(),
+                                       content,
+                                       content->GetNextSibling());
+    }
+  } else if (mOurA11yNotification == eNotifyHidden) {
+    nsAccessibilityService* accService = nsIPresShell::AccService();
+    if (accService) {
+      nsIPresShell* presShell = mFrame->PresContext()->GetPresShell();
+      nsIContent* content = mFrame->GetContent();
+      accService->ContentRemoved(presShell, content->GetParent(), content);
 
-              // reresolve placeholder's context under the same parent
-              // as the out-of-flow frame
-              ReResolveStyleContext(aPresContext, child, content,
-                                    aChangeList, aMinChange,
-                                    nonInheritedHints,
-                                    childRestyleHint,
-                                    aRestyleTracker,
-                                    kidsDesiredA11yNotification,
-                                    aVisibleKidsOfHiddenElement,
-                                    aTreeMatchContext);
-            }
-            else {  // regular child frame
-              if (child != resolvedChild) {
-                ReResolveStyleContext(aPresContext, child, content,
-                                      aChangeList, aMinChange,
-                                      nonInheritedHints,
-                                      childRestyleHint,
-                                      aRestyleTracker,
-                                      kidsDesiredA11yNotification,
-                                      aVisibleKidsOfHiddenElement,
-                                      aTreeMatchContext);
-              }
-            }
-          }
-        }
+      // Process children staying shown.
+      uint32_t visibleContentCount = mVisibleKidsOfHiddenElement.Length();
+      for (uint32_t idx = 0; idx < visibleContentCount; idx++) {
+        nsIContent* childContent = mVisibleKidsOfHiddenElement[idx];
+        accService->ContentRangeInserted(presShell, childContent->GetParent(),
+                                         childContent,
+                                         childContent->GetNextSibling());
       }
-      // XXX need to do overflow frames???
-
-#ifdef ACCESSIBILITY
-      // Send notifications about visibility changes.
-      if (ourA11yNotification == eNotifyShown) {
-        nsAccessibilityService* accService = nsIPresShell::AccService();
-        if (accService) {
-          nsIPresShell* presShell = aFrame->PresContext()->GetPresShell();
-          nsIContent* content = aFrame->GetContent();
-
-          accService->ContentRangeInserted(presShell, content->GetParent(),
-                                           content,
-                                           content->GetNextSibling());
-        }
-      } else if (ourA11yNotification == eNotifyHidden) {
-        nsAccessibilityService* accService = nsIPresShell::AccService();
-        if (accService) {
-          nsIPresShell* presShell = aFrame->PresContext()->GetPresShell();
-          nsIContent* content = aFrame->GetContent();
-          accService->ContentRemoved(presShell, content->GetParent(), content);
-
-          // Process children staying shown.
-          uint32_t visibleContentCount = aVisibleKidsOfHiddenElement.Length();
-          for (uint32_t idx = 0; idx < visibleContentCount; idx++) {
-            nsIContent* content = aVisibleKidsOfHiddenElement[idx];
-            accService->ContentRangeInserted(presShell, content->GetParent(),
-                                             content, content->GetNextSibling());
-          }
-          aVisibleKidsOfHiddenElement.Clear();
-        }
-      }
-#endif
+      mVisibleKidsOfHiddenElement.Clear();
     }
   }
-
-  return aMinChange;
+#endif
 }
 
 void
 RestyleManager::ComputeStyleChangeFor(nsIFrame*          aFrame,
                                       nsStyleChangeList* aChangeList,
                                       nsChangeHint       aMinChange,
                                       RestyleTracker&    aRestyleTracker,
                                       bool               aRestyleDescendants)
@@ -2613,27 +2701,24 @@ RestyleManager::ComputeStyleChangeFor(ns
   Element *parentElement =
     parent && parent->IsElement() ? parent->AsElement() : nullptr;
   treeMatchContext.InitAncestors(parentElement);
   nsTArray<nsIContent*> visibleKidsOfHiddenElement;
   do {
     // Outer loop over special siblings
     do {
       // Inner loop over next-in-flows of the current frame
-      nsChangeHint frameChange =
-        ReResolveStyleContext(mPresContext, frame, nullptr,
-                              aChangeList, aMinChange, nsChangeHint(0),
-                              aRestyleDescendants ?
-                                eRestyle_Subtree : eRestyle_Self,
-                              aRestyleTracker,
-                              eSendAllNotifications,
-                              visibleKidsOfHiddenElement,
-                              treeMatchContext);
+      ElementRestyler restyler(mPresContext, frame, aChangeList,
+                               aMinChange, aRestyleTracker,
+                               treeMatchContext,
+                               visibleKidsOfHiddenElement);
 
-      if (frameChange & nsChangeHint_ReconstructFrame) {
+      restyler.Restyle(aRestyleDescendants ? eRestyle_Subtree : eRestyle_Self);
+
+      if (restyler.HintsHandledForFrame() & nsChangeHint_ReconstructFrame) {
         // If it's going to cause a framechange, then don't bother
         // with the continuations or special siblings since they'll be
         // clobbered by the frame reconstruct anyway.
         NS_ASSERTION(!frame->GetPrevContinuation(),
                      "continuing frame had more severe impact than first-in-flow");
         return;
       }
 
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -21,17 +21,17 @@ class nsIFrame;
 struct TreeMatchContext;
 
 namespace mozilla {
 
 namespace dom {
   class Element;
 } // namespace dom
 
-class RestyleManager {
+class RestyleManager MOZ_FINAL {
 public:
   friend class ::nsRefreshDriver;
   friend class RestyleTracker;
 
   typedef mozilla::dom::Element Element;
 
   RestyleManager(nsPresContext* aPresContext);
 
@@ -140,16 +140,22 @@ public:
   // CreateNeededFrames.
   // Note: It's the caller's responsibility to make sure to wrap a
   // ProcessPendingRestyles call in a view update batch and a script blocker.
   // This function does not call ProcessAttachedQueue() on the binding manager.
   // If the caller wants that to happen synchronously, it needs to handle that
   // itself.
   void ProcessPendingRestyles();
 
+  // ProcessPendingRestyles calls into one of our RestyleTracker
+  // objects.  It then calls back to these functions at the beginning
+  // and end of its work.
+  void BeginProcessingRestyles();
+  void EndProcessingRestyles();
+
   // Rebuilds all style data by throwing out the old rule tree and
   // building a new one, and additionally applying aExtraHint (which
   // must not contain nsChangeHint_ReconstructFrame) to the root frame.
   void RebuildAllStyleData(nsChangeHint aExtraHint);
 
   // Helper that does part of the work of RebuildAllStyleData, shared by
   // RestyleElement for 'rem' handling.
   void DoRebuildAllStyleData(RestyleTracker& aRestyleTracker,
@@ -174,57 +180,22 @@ public:
     PostRestyleEventCommon(aElement, aRestyleHint, aMinChangeHint, true);
   }
 
   void PostRestyleEventForLazyConstruction()
   {
     PostRestyleEventInternal(true);
   }
 
-  void SetInStyleRefresh(bool aInStyleRefresh)
-  {
-    mInStyleRefresh = aInStyleRefresh;
-  }
-
   void FlushOverflowChangedTracker()
   {
     mOverflowChangedTracker.Flush();
   }
 
 private:
-  enum DesiredA11yNotifications {
-    eSkipNotifications,
-    eSendAllNotifications,
-    eNotifyIfShown
-  };
-
-  enum A11yNotificationType {
-    eDontNotify,
-    eNotifyShown,
-    eNotifyHidden
-  };
-
-  // Use eRestyle_Self for the aRestyleHint argument to mean
-  // "reresolve our style context but not kids", use eRestyle_Subtree
-  // to mean "reresolve our style context and kids", and use
-  // nsRestyleHint(0) to mean recompute a new style context for our
-  // current parent and existing rulenode, and the same for kids.
-  NS_HIDDEN_(nsChangeHint)
-    ReResolveStyleContext(nsPresContext* aPresContext,
-                          nsIFrame* aFrame,
-                          nsIContent* aParentContent,
-                          nsStyleChangeList* aChangeList,
-                          nsChangeHint aMinChange,
-                          nsChangeHint aParentFrameHintsNotHandledForDescendants,
-                          nsRestyleHint aRestyleHint,
-                          RestyleTracker& aRestyleTracker,
-                          DesiredA11yNotifications aDesiredA11yNotifications,
-                          nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
-                          TreeMatchContext& aTreeMatchContext);
-
   /**
    * Notify the frame constructor that an element needs to have its
    * style recomputed.
    * @param aElement: The element to be restyled.
    * @param aRestyleHint: Which nodes need to have selector matching run
    *                      on them.
    * @param aMinChangeHint: A minimum change hint for aContent and its
    *                        descendants.
@@ -286,11 +257,138 @@ private:
   // The total number of animation flushes by this frame constructor.
   // Used to keep the layer and animation manager in sync.
   uint64_t mAnimationGeneration;
 
   RestyleTracker mPendingRestyles;
   RestyleTracker mPendingAnimationRestyles;
 };
 
+/**
+ * An ElementRestyler is created for *each* element in a subtree that we
+ * recompute styles for.
+ */
+class ElementRestyler MOZ_FINAL {
+public:
+  typedef mozilla::dom::Element Element;
+
+  // Construct for the root of the subtree that we're restyling.
+  ElementRestyler(nsPresContext* aPresContext,
+                  nsIFrame* aFrame,
+                  nsStyleChangeList* aChangeList,
+                  nsChangeHint aHintsHandledByAncestors,
+                  RestyleTracker& aRestyleTracker,
+                  TreeMatchContext& aTreeMatchContext,
+                  nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement);
+
+  // Construct for an element whose parent is being restyled.
+  enum ConstructorFlags {
+    FOR_OUT_OF_FLOW_CHILD = 1<<0
+  };
+  ElementRestyler(const ElementRestyler& aParentRestyler,
+                  nsIFrame* aFrame,
+                  uint32_t aConstructorFlags);
+
+  // Construct for a frame whose parent is being restyled, but whose
+  // style context is the parent style context for its parent frame.
+  // (This is only used for table frames, whose style contexts are used
+  // as the parent style context for their outer table frame (table
+  // wrapper frame).  We should probably try to get rid of this
+  // exception and have the inheritance go the other way.)
+  enum ParentContextFromChildFrame { PARENT_CONTEXT_FROM_CHILD_FRAME };
+  ElementRestyler(ParentContextFromChildFrame,
+                  const ElementRestyler& aParentFrameRestyler,
+                  nsIFrame* aFrame);
+
+  /**
+   * Restyle our frame's element and its subtree.
+   *
+   * Use eRestyle_Self for the aRestyleHint argument to mean
+   * "reresolve our style context but not kids", use eRestyle_Subtree
+   * to mean "reresolve our style context and kids", and use
+   * nsRestyleHint(0) to mean recompute a new style context for our
+   * current parent and existing rulenode, and the same for kids.
+   */
+  void Restyle(nsRestyleHint aRestyleHint);
+
+  /**
+   * mHintsHandled changes over time; it starts off as the hints that
+   * have been handled by ancestors, and by the end of Restyle it
+   * represents the hints that have been handled for this frame.  This
+   * method is intended to be called after Restyle, to find out what
+   * hints have been handled for this frame.
+   */
+  nsChangeHint HintsHandledForFrame() { return mHintsHandled; }
+
+private:
+  /**
+   * First half of Restyle().
+   */
+  void RestyleSelf(nsRestyleHint aRestyleHint);
+
+  /**
+   * Restyle the children of this frame (and, in turn, their children).
+   *
+   * Second half of Restyle().
+   */
+  void RestyleChildren(nsRestyleHint aChildRestyleHint);
+
+  /**
+   * Helper for RestyleSelf().
+   */
+  void CaptureChange(nsStyleContext* aOldContext,
+                     nsStyleContext* aNewContext,
+                     nsChangeHint aChangeToAssume);
+
+  /**
+   * Helpers for RestyleChildren().
+   */
+  void RestyleUndisplayedChildren(nsRestyleHint aChildRestyleHint);
+  void RestyleBeforePseudo();
+  void RestyleAfterPseudo();
+  void RestyleContentChildren(nsRestyleHint aChildRestyleHint);
+  void InitializeAccessibilityNotifications();
+  void SendAccessibilityNotifications();
+
+  enum DesiredA11yNotifications {
+    eSkipNotifications,
+    eSendAllNotifications,
+    eNotifyIfShown
+  };
+
+  enum A11yNotificationType {
+    eDontNotify,
+    eNotifyShown,
+    eNotifyHidden
+  };
+
+private:
+  nsPresContext* const mPresContext;
+  nsIFrame* const mFrame;
+  nsIContent* const mParentContent;
+  // |mContent| is the node that we used for rule matching of
+  // normal elements (not pseudo-elements) and for which we generate
+  // framechange hints if we need them.
+  nsIContent* const mContent;
+  nsStyleChangeList* const mChangeList;
+  // We have already generated change list entries for hints listed in
+  // mHintsHandled (initially it's those handled by ancestors, but by
+  // the end of Restyle it is those handled for this frame as well).  We
+  // need to generate a new change list entry for the frame when its
+  // style comparision returns a hint other than one of these hints.
+  nsChangeHint mHintsHandled;
+  // See nsStyleContext::CalcStyleDifference
+  nsChangeHint mParentFrameHintsNotHandledForDescendants;
+  nsChangeHint mHintsNotHandledForDescendants;
+  RestyleTracker& mRestyleTracker;
+  TreeMatchContext& mTreeMatchContext;
+  nsIFrame* mResolvedChild; // child that provides our parent style context
+
+  const DesiredA11yNotifications mDesiredA11yNotifications;
+  DesiredA11yNotifications mKidsDesiredA11yNotifications;
+  A11yNotificationType mOurA11yNotification;
+  nsTArray<nsIContent*>& mVisibleKidsOfHiddenElement;
+  bool mWasFrameVisible;
+};
+
 } // namespace mozilla
 
 #endif /* mozilla_RestyleManager_h */
--- a/layout/base/RestyleTracker.cpp
+++ b/layout/base/RestyleTracker.cpp
@@ -130,21 +130,18 @@ RestyleTracker::ProcessOneRestyle(Elemen
     mRestyleManager->ProcessRestyledFrames(changeList);
   }
 }
 
 void
 RestyleTracker::DoProcessRestyles()
 {
   PROFILER_LABEL("CSS", "ProcessRestyles");
-  // Make sure to not rebuild quote or counter lists while we're
-  // processing restyles
-  mRestyleManager->PresContext()->FrameConstructor()->BeginUpdate();
 
-  mRestyleManager->SetInStyleRefresh(true);
+  mRestyleManager->BeginProcessingRestyles();
 
   // loop so that we process any restyle events generated by processing
   while (mPendingRestyles.Count()) {
     if (mHaveLaterSiblingRestyles) {
       // Convert them to individual restyles on all the later siblings
       nsAutoTArray<nsRefPtr<Element>, RESTYLE_ARRAY_STACKSIZE> laterSiblingArr;
       LaterSiblingCollector siblingCollector = { this, &laterSiblingArr };
       mPendingRestyles.Enumerate(CollectLaterSiblings, &siblingCollector);
@@ -234,27 +231,17 @@ RestyleTracker::DoProcessRestyles()
            ++currentRestyle) {
         ProcessOneRestyle(currentRestyle->mElement,
                           currentRestyle->mRestyleHint,
                           currentRestyle->mChangeHint);
       }
     }
   }
 
-  mRestyleManager->FlushOverflowChangedTracker();
-
-  // SetInStyleRefresh(false) now, since the EndUpdate call might
-  // add more restyles.
-  mRestyleManager->SetInStyleRefresh(false);
-
-  mRestyleManager->PresContext()->FrameConstructor()->EndUpdate();
-
-#ifdef DEBUG
-  mRestyleManager->PresContext()->PresShell()->VerifyStyleTree();
-#endif
+  mRestyleManager->EndProcessingRestyles();
 }
 
 bool
 RestyleTracker::GetRestyleData(Element* aElement, RestyleData* aData)
 {
   NS_PRECONDITION(aElement->GetCurrentDoc() == Document(),
                   "Unexpected document; this will lead to incorrect behavior!");
 
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -64,17 +64,16 @@ EXPORTS += [
     'nsIPresShell.h',
     'nsIReflowCallback.h',
     'nsLayoutUtils.h',
     'nsPresArena.h',
     'nsPresContext.h',
     'nsPresState.h',
     'nsRefreshDriver.h',
     'nsStyleChangeList.h',
-    'nsStyleConsts.h',
 ]
 
 EXPORTS.mozilla += [
     'PaintTracker.h',
 ]
 
 CPP_SOURCES += [
     'DisplayItemClip.cpp',
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -37,16 +37,17 @@
 #include "nsStyleSet.h"
 #include "nsViewManager.h"
 #include "nsEventStates.h"
 #include "nsStyleConsts.h"
 #include "nsTableOuterFrame.h"
 #include "nsIDOMXULElement.h"
 #include "nsContainerFrame.h"
 #include "nsINameSpaceManager.h"
+#include "nsIDOMHTMLLegendElement.h"
 #include "nsIComboboxControlFrame.h"
 #include "nsIListControlFrame.h"
 #include "nsISelectControlFrame.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsPlaceholderFrame.h"
 #include "nsTableRowGroupFrame.h"
 #include "nsIFormControl.h"
@@ -5873,17 +5874,17 @@ nsCSSFrameConstructor::IsValidSibling(ns
 
     return true;
   }
   else if (nsGkAtoms::fieldSetFrame == parentType ||
            (nsGkAtoms::fieldSetFrame == grandparentType &&
             nsGkAtoms::blockFrame == parentType)) {
     // Legends can be sibling of legends but not of other content in the fieldset
     nsIAtom* sibType = aSibling->GetContentInsertionFrame()->GetType();
-    bool legendContent = aContent->IsHTML(nsGkAtoms::legend);
+    nsCOMPtr<nsIDOMHTMLLegendElement> legendContent(do_QueryInterface(aContent));
 
     if ((legendContent  && (nsGkAtoms::legendFrame != sibType)) ||
         (!legendContent && (nsGkAtoms::legendFrame == sibType)))
       return false;
   }
 
   return true;
 }
@@ -5981,17 +5982,18 @@ GetAdjustedParentFrame(nsIFrame*       a
   NS_PRECONDITION(nsGkAtoms::tableOuterFrame != aParentFrameType,
                   "Shouldn't be happening!");
   
   nsIFrame* newParent = nullptr;
 
   if (nsGkAtoms::fieldSetFrame == aParentFrameType) {
     // If the parent is a fieldSet, use the fieldSet's area frame as the
     // parent unless the new content is a legend. 
-    if (!aChildContent->IsHTML(nsGkAtoms::legend)) {
+    nsCOMPtr<nsIDOMHTMLLegendElement> legendContent(do_QueryInterface(aChildContent));
+    if (!legendContent) {
       newParent = GetFieldSetBlockFrame(aParentFrame);
     }
   }
   return (newParent) ? newParent : aParentFrame;
 }
 
 nsIFrame*
 nsCSSFrameConstructor::GetInsertionPrevSibling(nsIFrame*& aParentFrame,
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -202,17 +202,17 @@ public:
    */
   virtual NS_HIDDEN_(void) MakeZombie() = 0;
 
   /**
    * All frames owned by the shell are allocated from an arena.  They
    * are also recycled using free lists.  Separate free lists are
    * maintained for each frame type (aID), which must always correspond
    * to the same aSize value.  AllocateFrame returns zero-filled memory.
-   * AllocateFrame is fallible, it returns nullptr on out-of-memory.
+   * AllocateFrame is infallible and will abort on out-of-memory.
    */
   void* AllocateFrame(nsQueryFrame::FrameIID aID, size_t aSize)
   {
 #ifdef DEBUG
     mPresArenaAllocCount++;
 #endif
     void* result = mFrameArena.AllocateByFrameID(aID, aSize);
     memset(result, 0, aSize);
@@ -227,17 +227,17 @@ public:
     if (!mIsDestroying)
       mFrameArena.FreeByFrameID(aID, aPtr);
   }
 
   /**
    * This is for allocating other types of objects (not frames).  Separate free
    * lists are maintained for each type (aID), which must always correspond to
    * the same aSize value.  AllocateByObjectID returns zero-filled memory.
-   * AllocateByObjectID is fallible, it returns nullptr on out-of-memory.
+   * AllocateByObjectID is infallible and will abort on out-of-memory.
    */
   void* AllocateByObjectID(nsPresArena::ObjectID aID, size_t aSize)
   {
 #ifdef DEBUG
     mPresArenaAllocCount++;
 #endif
     void* result = mFrameArena.AllocateByObjectID(aID, aSize);
     memset(result, 0, aSize);
@@ -253,17 +253,17 @@ public:
       mFrameArena.FreeByObjectID(aID, aPtr);
   }
 
   /**
    * Other objects closely related to the frame tree that are allocated
    * from a separate set of per-size free lists.  Note that different types
    * of objects that has the same size are allocated from the same list.
    * AllocateMisc does *not* clear the memory that it returns.
-   * AllocateMisc is fallible, it returns nullptr on out-of-memory.
+   * AllocateMisc is infallible and will abort on out-of-memory.
    *
    * @deprecated use AllocateByObjectID/FreeByObjectID instead
    */
   void* AllocateMisc(size_t aSize)
   {
 #ifdef DEBUG
     mPresArenaAllocCount++;
 #endif
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -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/. */
 
 #include "nsCSSAnonBoxes.h"
 #include "nsContainerFrame.h"
 #include "nsLegendFrame.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMHTMLFieldSetElement.h"
+#include "nsIDOMHTMLLegendElement.h"
 #include "nsCSSRendering.h"
 #include <algorithm>
 #include "nsIContent.h"
 #include "nsIFrame.h"
 #include "nsISupports.h"
 #include "nsIAtom.h"
 #include "nsPresContext.h"
 #include "RestyleManager.h"
--- a/layout/forms/nsMeterFrame.cpp
+++ b/layout/forms/nsMeterFrame.cpp
@@ -1,34 +1,33 @@
 /* -*- 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/. */
 
 #include "nsMeterFrame.h"
 
+#include "nsIDOMHTMLMeterElement.h"
 #include "nsIContent.h"
 #include "nsPresContext.h"
 #include "nsGkAtoms.h"
 #include "nsINameSpaceManager.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsNodeInfoManager.h"
 #include "nsINodeInfo.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
 #include "nsFormControlFrame.h"
 #include "nsFontMetrics.h"
 #include "nsContentList.h"
 #include "mozilla/dom/Element.h"
-#include "mozilla/dom/HTMLMeterElement.h"
 #include "nsContentList.h"
 #include <algorithm>
 
-using mozilla::dom::HTMLMeterElement;
 
 nsIFrame*
 NS_NewMeterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsMeterFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsMeterFrame)
@@ -146,23 +145,25 @@ nsMeterFrame::ReflowBarFrame(nsIFrame*  
                                 nsSize(aReflowState.ComputedWidth(),
                                        NS_UNCONSTRAINEDSIZE));
   nscoord size = vertical ? aReflowState.ComputedHeight()
                           : aReflowState.ComputedWidth();
   nscoord xoffset = aReflowState.mComputedBorderPadding.left;
   nscoord yoffset = aReflowState.mComputedBorderPadding.top;
 
   // NOTE: Introduce a new function getPosition in the content part ?
-  HTMLMeterElement* meterElement = static_cast<HTMLMeterElement*>(mContent);
+  double position, max, min, value;
+  nsCOMPtr<nsIDOMHTMLMeterElement> meterElement =
+    do_QueryInterface(mContent);
 
-  double max = meterElement->Max();
-  double min = meterElement->Min();
-  double value = meterElement->Value();
+  meterElement->GetMax(&max);
+  meterElement->GetMin(&min);
+  meterElement->GetValue(&value);
 
-  double position = max - min;
+  position = max - min;
   position = position != 0 ? (value - min) / position : 1;
 
   size = NSToCoordRound(size * position);
 
   if (!vertical && StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
     xoffset += aReflowState.ComputedWidth() - size;
   }
 
--- a/layout/forms/nsProgressFrame.cpp
+++ b/layout/forms/nsProgressFrame.cpp
@@ -1,34 +1,33 @@
 /* -*- 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/. */
 
 #include "nsProgressFrame.h"
 
+#include "nsIDOMHTMLProgressElement.h"
 #include "nsIContent.h"
 #include "nsPresContext.h"
 #include "nsGkAtoms.h"
 #include "nsINameSpaceManager.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsNodeInfoManager.h"
 #include "nsINodeInfo.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
 #include "nsFormControlFrame.h"
 #include "nsContentList.h"
 #include "nsFontMetrics.h"
 #include "mozilla/dom/Element.h"
-#include "mozilla/dom/HTMLProgressElement.h"
 #include "nsContentList.h"
 #include <algorithm>
 
-using namespace mozilla::dom;
 
 nsIFrame*
 NS_NewProgressFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsProgressFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsProgressFrame)
@@ -153,17 +152,20 @@ nsProgressFrame::ReflowBarFrame(nsIFrame
   nsHTMLReflowState reflowState(aPresContext, aReflowState, aBarFrame,
                                 nsSize(aReflowState.ComputedWidth(),
                                        NS_UNCONSTRAINEDSIZE));
   nscoord size = vertical ? aReflowState.ComputedHeight()
                           : aReflowState.ComputedWidth();
   nscoord xoffset = aReflowState.mComputedBorderPadding.left;
   nscoord yoffset = aReflowState.mComputedBorderPadding.top;
 
-  double position = static_cast<HTMLProgressElement*>(mContent)->Position();
+  double position;
+  nsCOMPtr<nsIDOMHTMLProgressElement> progressElement =
+    do_QueryInterface(mContent);
+  progressElement->GetPosition(&position);
 
   // Force the bar's size to match the current progress.
   // When indeterminate, the progress' size will be 100%.
   if (position >= 0.0) {
     size *= position;
   }
 
   if (!vertical && StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -76,17 +76,17 @@ CPP_SOURCES += [
     'nsObjectFrame.cpp',
     'nsPageContentFrame.cpp',
     'nsPageFrame.cpp',
     'nsPlaceholderFrame.cpp',
     'nsSelection.cpp',
     'nsSimplePageSequence.cpp',
     'nsSplittableFrame.cpp',
     'nsSubDocumentFrame.cpp',
-    'nsTextFrameThebes.cpp',
+    'nsTextFrame.cpp',
     'nsTextFrameUtils.cpp',
     'nsTextRunTransformations.cpp',
     'nsVideoFrame.cpp',
     'nsViewportFrame.cpp',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     CMMSRCS += [
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -699,26 +699,26 @@ nsFrame::GetOffsets(int32_t &aStart, int
 nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   if (IsSVGText()) {
     nsSVGTextFrame2* svgTextFrame = static_cast<nsSVGTextFrame2*>(
         nsLayoutUtils::GetClosestFrameOfType(this, nsGkAtoms::svgTextFrame2));
     nsIFrame* anonBlock = svgTextFrame->GetFirstPrincipalChild();
     // Just as in nsSVGTextFrame2::DidSetStyleContext, we need to ensure that
     // any non-display nsSVGTextFrame2s get reflowed when a child text frame
-    // gets new style.  We don't need to do this when the frame has not yet
-    // been reflowed, since that will happen soon anyway.
+    // gets new style.
     //
     // Note that we must check NS_FRAME_FIRST_REFLOW on our nsSVGTextFrame2's
     // anonymous block frame rather than our self, since NS_FRAME_FIRST_REFLOW
     // may be set on us if we're a new frame that has been inserted after the
     // document's first reflow. (In which case this DidSetStyleContext call may
     // be happening under frame construction under a Reflow() call.)
     if (anonBlock && !(anonBlock->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
-        (svgTextFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
+        (svgTextFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY) &&
+        !(svgTextFrame->GetStateBits() & NS_STATE_SVG_TEXT_IN_REFLOW)) {
       svgTextFrame->ScheduleReflowSVGNonDisplayText();
     }
   }
 
   ImageLoader* imageLoader = PresContext()->Document()->StyleImageLoader();
 
   // If the old context had a background image image and new context
   // does not have the same image, clear the image load notifier
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -754,17 +754,23 @@ public:
       if (aContext) {
         aContext->AddRef();
         DidSetStyleContext(oldStyleContext);
       }
       if (oldStyleContext)
         oldStyleContext->Release();
     }
   }
-  
+
+  /**
+   * SetStyleContextWithoutNotification is for changes to the style
+   * context that should suppress style change processing, in other
+   * words, those that aren't really changes.  This generally means only
+   * changes that happen during frame construction.
+   */
   void SetStyleContextWithoutNotification(nsStyleContext* aContext)
   {
     if (aContext != mStyleContext) {
       if (mStyleContext)
         mStyleContext->Release();
       mStyleContext = aContext;
       if (aContext) {
         aContext->AddRef();
rename from layout/generic/nsTextFrameThebes.cpp
rename to layout/generic/nsTextFrame.cpp
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -42,16 +42,17 @@ EXPORTS += [
     'nsIStyleRuleProcessor.h',
     'nsIStyleSheet.h',
     'nsLayoutStylesheetCache.h',
     'nsRuleData.h',
     'nsRuleNode.h',
     'nsRuleProcessorData.h',
     'nsRuleWalker.h',
     'nsStyleAnimation.h',
+    'nsStyleConsts.h',
     'nsStyleContext.h',
     'nsStyleCoord.h',
     'nsStyleSet.h',
     'nsStyleStruct.h',
     'nsStyleStructFwd.h',
     'nsStyleStructInlines.h',
     'nsStyleStructList.h',
     'nsStyleTransformMatrix.h',
rename from layout/base/nsStyleConsts.h
rename to layout/style/nsStyleConsts.h
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -785,26 +785,21 @@ nsStyleSet::GetContext(nsStyleContext* a
     fprintf(stdout, "--- SharedSC %d ---\n", ++gSharedCount);
   else
     fprintf(stdout, "+++ NewSC %d +++\n", ++gNewCount);
 #endif
 
   if (!result) {
     result = NS_NewStyleContext(aParentContext, aPseudoTag, aPseudoType,
                                 aRuleNode, aFlags & eSkipFlexItemStyleFixup);
-    if (!result)
-      return nullptr;
     if (aVisitedRuleNode) {
       nsRefPtr<nsStyleContext> resultIfVisited =
         NS_NewStyleContext(parentIfVisited, aPseudoTag, aPseudoType,
                            aVisitedRuleNode,
                            aFlags & eSkipFlexItemStyleFixup);
-      if (!resultIfVisited) {
-        return nullptr;
-      }
       if (!parentIfVisited) {
         mRoots.AppendElement(resultIfVisited);
       }
       resultIfVisited->SetIsStyleIfVisited();
       result->SetStyleIfVisited(resultIfVisited.forget());
 
       bool relevantLinkVisited = (aFlags & eIsLink) ?
         (aFlags & eIsVisitedLink) :
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -214,23 +214,23 @@ static void ReparentBeforeAndAfter(dom::
                                    nsIFrame* aPrimaryFrame,
                                    nsStyleContext* aNewStyle,
                                    nsStyleSet* aStyleSet)
 {
   if (nsIFrame* before = nsLayoutUtils::GetBeforeFrame(aPrimaryFrame)) {
     nsRefPtr<nsStyleContext> beforeStyle =
       aStyleSet->ReparentStyleContext(before->StyleContext(),
                                      aNewStyle, aElement);
-    before->SetStyleContextWithoutNotification(beforeStyle);
+    before->SetStyleContext(beforeStyle);
   }
   if (nsIFrame* after = nsLayoutUtils::GetBeforeFrame(aPrimaryFrame)) {
     nsRefPtr<nsStyleContext> afterStyle =
       aStyleSet->ReparentStyleContext(after->StyleContext(),
                                      aNewStyle, aElement);
-    after->SetStyleContextWithoutNotification(afterStyle);
+    after->SetStyleContext(afterStyle);
   }
 }
 
 // Ensure that the next repaint rebuilds the layer tree for aFrame. That
 // means that changes to animations on aFrame's layer are propagated to
 // the compositor, which is needed for correct behaviour of new
 // transitions.
 static void
@@ -313,17 +313,17 @@ nsTransitionManager::UpdateThrottledStyl
   // We absolutely must call CalcStyleDifference in order to ensure the
   // new context has all the structs cached that the old context had.
   // We also need it for processing of the changes.
   nsChangeHint styleChange =
     oldStyle->CalcStyleDifference(newStyle, nsChangeHint(0));
   aChangeList.AppendChange(primaryFrame, primaryFrame->GetContent(),
                            styleChange);
 
-  primaryFrame->SetStyleContextWithoutNotification(newStyle);
+  primaryFrame->SetStyleContext(newStyle);
 
   ReparentBeforeAndAfter(aElement, primaryFrame, newStyle, mPresContext->PresShell()->StyleSet());
 
   return newStyle;
 }
 
 void
 nsTransitionManager::UpdateThrottledStylesForSubtree(nsIContent* aContent,
@@ -353,17 +353,17 @@ nsTransitionManager::UpdateThrottledStyl
     nsStyleSet* styleSet = mPresContext->PresShell()->StyleSet();
     nsIFrame* primaryFrame = nsLayoutUtils::GetStyleFrame(aContent);
     if (!primaryFrame) {
       return;
     }
 
     newStyle = styleSet->ReparentStyleContext(primaryFrame->StyleContext(),
                                               aParentStyle, element);
-    primaryFrame->SetStyleContextWithoutNotification(newStyle);
+    primaryFrame->SetStyleContext(newStyle);
     ReparentBeforeAndAfter(element, primaryFrame, newStyle, styleSet);
   }
 
   // walk the children
   if (newStyle) {
     for (nsIContent *child = aContent->GetFirstChild(); child;
          child = child->GetNextSibling()) {
       UpdateThrottledStylesForSubtree(child, newStyle, aChangeList);
--- a/layout/style/test/Makefile.in
+++ b/layout/style/test/Makefile.in
@@ -82,16 +82,17 @@ MOCHITEST_FILES =	test_acid3_test46.html
 		file_bug645998-1.css \
 		file_bug645998-2.css \
 		test_bug716226.html \
 		test_bug765590.html \
 		test_bug798567.html \
 		test_bug829816.html \
 		file_bug829816.css \
 		test_bug887741_at-rules_in_declaration_lists.html \
+		test_bug892929.html \
 		test_cascade.html \
 		test_ch_ex_no_infloops.html \
 		test_compute_data_with_start_struct.html \
 		test_computed_style.html \
 		test_computed_style_no_pseudo.html \
 		test_condition_text.html \
 		test_condition_text_assignment.html \
 		test_default_computed_style.html \
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_bug892929.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset=utf-8>
+  <title>Bug 892929 test</title>
+  <link rel="author" title="John Daggett" href="mailto:jdaggett@mozilla.com">
+  <link rel="help" href="http://www.w3.org/TR/css-fonts-3/#om-fontfeaturevalues" />
+  <meta name="assert" content="window.CSSFontFeatureValuesRule should only appear when layout.css.font-features.enabled is true" />
+  <script type="text/javascript" src="/resources/testharness.js"></script>
+  <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+  <style type="text/css">
+  </style>
+</head>
+<body>
+<div id="log"></div>
+<pre id="display"></pre>
+
+<script type="text/javascript">
+
+function testCSSFontFeatureValuesRuleOM() {
+  var s = document.documentElement.style;
+  var cs = window.getComputedStyle(document.documentElement);
+
+  var hasFFVRule = "CSSFontFeatureValuesRule" in window;
+  var hasStyleAlternates = "fontVariantAlternates" in s;
+  var hasCompStyleAlternates = "fontVariantAlternates" in cs;
+
+  test(function() {
+    assert_equals(hasFFVRule,
+                  hasStyleAlternates,
+                  "style.fontVariantAlternates " +
+                    (hasStyleAlternates ? "available" : "not available") +
+                    " but " +
+                    "window.CSSFontFeatureValuesRule " +
+                    (hasFFVRule ? "available" : "not available") +
+                    " - ");
+  }, "style.fontVariantAlternates availability matches window.CSSFontFeatureValuesRule availability");
+
+  test(function() {
+    assert_equals(hasFFVRule,
+                  hasCompStyleAlternates,
+                  "computedStyle.fontVariantAlternates " +
+                    (hasCompStyleAlternates ? "available" : "not available") +
+                    " but " +
+                    "window.CSSFontFeatureValuesRule " +
+                    (hasFFVRule ? "available" : "not available") +
+                    " - ");
+  }, "computedStyle.fontVariantAlternates availability matches window.CSSFontFeatureValuesRule availability");
+
+  // if window.CSSFontFeatureValuesRule isn't around, neither should any of the font feature props
+  fontFeatureProps = [ "fontKerning", "fontVariantAlternates", "fontVariantCaps", "fontVariantEastAsian",
+                       "fontVariantLigatures", "fontVariantNumeric", "fontVariantPosition", "fontSynthesis",
+                       "fontFeatureSettings", "fontLanguageOverride" ];
+
+  if (!hasFFVRule) {
+    var i;
+    for (i = 0; i < fontFeatureProps.length; i++) {
+      var prop = fontFeatureProps[i];
+      test(function() {
+             assert_true(!(prop in s), "window.CSSFontFeatureValuesRule not available but style." + prop + " is available - ");
+           }, "style." + prop + " availability");
+      test(function() {
+             assert_true(!(prop in cs), "window.CSSFontFeatureValuesRule not available but computedStyle." + prop + " is available - ");
+           }, "computedStyle." + prop + " availability");
+    }
+  }
+
+}
+
+testCSSFontFeatureValuesRuleOM();
+
+</script>
+</body>
+</html>
--- a/layout/svg/nsSVGTextFrame2.cpp
+++ b/layout/svg/nsSVGTextFrame2.cpp
@@ -3165,16 +3165,19 @@ nsSVGTextFrame2::ReflowSVGNonDisplayText
 }
 
 void
 nsSVGTextFrame2::ScheduleReflowSVGNonDisplayText()
 {
   MOZ_ASSERT(!nsSVGUtils::OuterSVGIsCallingReflowSVG(this),
              "do not call ScheduleReflowSVGNonDisplayText when the outer SVG "
              "frame is under ReflowSVG");
+  MOZ_ASSERT(!(mState & NS_STATE_SVG_TEXT_IN_REFLOW),
+             "do not call ScheduleReflowSVGNonDisplayText while reflowing the "
+             "anonymous block child");
 
   // We need to find an ancestor frame that we can call FrameNeedsReflow
   // on that will cause the document to be marked as needing relayout,
   // and for that ancestor (or some further ancestor) to be marked as
   // a root to reflow.  We choose the closest ancestor frame that is not
   // NS_FRAME_IS_NONDISPLAY and which is either an outer SVG frame or a
   // non-SVG frame.  (We don't consider displayed SVG frame ancestors toerh
   // than nsSVGOuterSVGFrame, since calling FrameNeedsReflow on those other
@@ -5039,16 +5042,18 @@ nsSVGTextFrame2::DoReflow()
     return;
 
   if (UpdateFontSizeScaleFactor()) {
     // If the font size scale factor changed, we need the block to report
     // an updated preferred width.
     kid->MarkIntrinsicWidthsDirty();
   }
 
+  mState |= NS_STATE_SVG_TEXT_IN_REFLOW;
+
   nscoord width = kid->GetPrefWidth(renderingContext);
   nsHTMLReflowState reflowState(presContext, kid,
                                 renderingContext,
                                 nsSize(width, NS_UNCONSTRAINEDSIZE));
   nsHTMLReflowMetrics desiredSize;
   nsReflowStatus status;
 
   NS_ASSERTION(reflowState.mComputedBorderPadding == nsMargin(0, 0, 0, 0) &&
@@ -5056,16 +5061,18 @@ nsSVGTextFrame2::DoReflow()
                "style system should ensure that :-moz-svg-text "
                "does not get styled");
 
   kid->WillReflow(presContext);
   kid->Reflow(presContext, desiredSize, reflowState, status);
   kid->DidReflow(presContext, &reflowState, nsDidReflowStatus::FINISHED);
   kid->SetSize(nsSize(desiredSize.width, desiredSize.height));
 
+  mState &= ~NS_STATE_SVG_TEXT_IN_REFLOW;
+
   TextNodeCorrespondenceRecorder::RecordCorrespondence(this);
 }
 
 // Usable font size range in devpixels / user-units
 #define CLAMP_MIN_SIZE 8.0
 #define CLAMP_MAX_SIZE 200.0
 #define PRECISE_SIZE   200.0
 
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -98,16 +98,18 @@ class Element;
  * first example above shows that NS_STATE_SVG_POSITIONING_MAY_USE_PERCENTAGES
  * can be true even if a viewport size change will not affect mPositions,
  * determining a completley accurate value for
  * NS_STATE_SVG_POSITIONING_MAY_USE_PERCENTAGES would require extra work that is
  * probably not worth it.
  */
 #define NS_STATE_SVG_POSITIONING_MAY_USE_PERCENTAGES NS_FRAME_STATE_BIT(23)
 
+#define NS_STATE_SVG_TEXT_IN_REFLOW              NS_FRAME_STATE_BIT(24)
+
 /**
  * Byte offsets of channels in a native packed gfxColor or cairo image surface.
  */
 #ifdef IS_BIG_ENDIAN
 #define GFX_ARGB32_OFFSET_A 0
 #define GFX_ARGB32_OFFSET_R 1
 #define GFX_ARGB32_OFFSET_G 2
 #define GFX_ARGB32_OFFSET_B 3
--- a/layout/tools/recording/recording.js
+++ b/layout/tools/recording/recording.js
@@ -1,53 +1,47 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
+/* -*- Mode: js; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
 /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
 /* 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/. */
 
 const CC = Components.classes;
 const CI = Components.interfaces;
-const CR = Components.results;
 
-const XHTML_NS = "http://www.w3.org/1999/xhtml";
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const NS_GFXINFO_CONTRACTID = "@mozilla.org/gfx/info;1";
 
 var gContainingWindow = null;
 
 var gBrowser;
 
-function OnDocumentLoad() {
+function OnDocumentLoad(evt) {
+dump(evt.target.location + "\n");
+    if (evt.target.location == "about:blank")
+        return;
     gContainingWindow.close();
 }
 
 this.OnRecordingLoad = function OnRecordingLoad(win) {
-    var prefs = Components.classes["@mozilla.org/preferences-service;1"].
-                getService(Components.interfaces.nsIPrefBranch);
-
     if (win === undefined || win == null) {
         win = window;
     }
     if (gContainingWindow == null && win != null) {
         gContainingWindow = win;
     }
 
     gBrowser = gContainingWindow.document.getElementById("browser");
 
     var gfxInfo = (NS_GFXINFO_CONTRACTID in CC) && CC[NS_GFXINFO_CONTRACTID].getService(CI.nsIGfxInfo);
     var info = gfxInfo.getInfo();
-    dump(info.AzureContentBackend);
+    dump(info.AzureContentBackend + "\n");
     if (info.AzureContentBackend == "none") {
         alert("Page recordings may only be made with Azure content enabled.");
         gContainingWindow.close();
         return;
     }
 
     gContainingWindow.document.addEventListener("load", OnDocumentLoad, true);
 
     var args = window.arguments[0].wrappedJSObject;
 
     gBrowser.loadURI(args.uri);
-}
-
-function OnRecordingUnload() {
-}
+};
--- a/layout/tools/recording/recording.xul
+++ b/layout/tools/recording/recording.xul
@@ -9,14 +9,13 @@
 }
 
 " ?>
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         id="recording-window"
         hidechrome="true"
         onload="OnRecordingLoad();"
-        onunload="OnRecordingUnload();"
         style="background:white; overflow:hidden; width:800px; height:600px;"
         >
     <script type="application/ecmascript" src="recording.js" />
   <browser id="browser" type="content-primary" style="min-width: 1024px; min-height: 768px; max-width: 1024px; max-height: 768px"/>
 </window>
--- a/mobile/android/base/background/healthreport/HealthReportConstants.java.in
+++ b/mobile/android/base/background/healthreport/HealthReportConstants.java.in
@@ -44,16 +44,17 @@ public class HealthReportConstants {
 
   public static final String PREF_MAXIMUM_FAILURES_PER_DAY = "healthreport_maximum_failures_per_day";
   public static final long DEFAULT_MAXIMUM_FAILURES_PER_DAY = 2;
 
   // Authoritative.
   public static final String PREF_FIRST_RUN = "healthreport_first_run";
   public static final String PREF_NEXT_SUBMISSION = "healthreport_next_submission";
   public static final String PREF_CURRENT_DAY_FAILURE_COUNT = "healthreport_current_day_failure_count";
+  public static final String PREF_CURRENT_DAY_RESET_TIME = "healthreport_current_day_reset_time";
 
   // Forensic.
   public static final String PREF_LAST_UPLOAD_REQUESTED = "healthreport_last_upload_requested";
   public static final String PREF_LAST_UPLOAD_SUCCEEDED = "healthreport_last_upload_succeeded";
   public static final String PREF_LAST_UPLOAD_FAILED = "healthreport_last_upload_failed";
 
   // Preferences for deleting obsolete documents.
   public static final String PREF_MINIMUM_TIME_BETWEEN_DELETES = "healthreport_time_between_deletes";
--- a/mobile/android/base/background/healthreport/upload/SubmissionPolicy.java
+++ b/mobile/android/base/background/healthreport/upload/SubmissionPolicy.java
@@ -118,21 +118,33 @@ public class SubmissionPolicy {
       // Make sure we start clean and as soon as possible.
       editor()
         .setFirstRunLocalTime(firstRun)
         .setNextSubmission(localTime + getMinimumTimeBeforeFirstSubmission())
         .setCurrentDayFailureCount(0)
         .commit();
     }
 
+    // This case will occur if the nextSubmission time is not set (== -1) but firstRun is.
     if (localTime < firstRun + getMinimumTimeBeforeFirstSubmission()) {
       Logger.info(LOG_TAG, "Need to wait " + getMinimumTimeBeforeFirstSubmission() + " before first upload.");
       return false;
     }
 
+    // The first upload attempt for a given document submission begins a 24-hour period in which
+    // the upload will retry upon a soft failure. At the end of this period, the submission
+    // failure count is reset, ensuring each day's first submission attempt has a zeroed failure
+    // count. A period may also end on upload success or hard failure.
+    if (localTime >= getCurrentDayResetTime()) {
+      editor()
+        .setCurrentDayResetTime(localTime + getMinimumTimeBetweenUploads())
+        .setCurrentDayFailureCount(0)
+        .commit();
+    }
+
     String id = HealthReportUtils.generateDocumentId();
     Collection<String> oldIds = tracker.getBatchOfObsoleteIds();
     tracker.addObsoleteId(id);
 
     Editor editor = editor();
     editor.setLastUploadRequested(localTime); // Write committed by delegate.
     client.upload(localTime, id, oldIds, new UploadDelegate(editor, oldIds));
     return true;
@@ -165,16 +177,17 @@ public class SubmissionPolicy {
     public void onSuccess(long localTime, String id) {
       long next = localTime + getMinimumTimeBetweenUploads();
       tracker.markIdAsUploaded(id);
       tracker.purgeObsoleteIds(oldIds);
       editor
         .setNextSubmission(next)
         .setLastUploadSucceeded(localTime)
         .setCurrentDayFailureCount(0)
+        .clearCurrentDayResetTime() // Set again on the next submission's first upload attempt.
         .commit();
       if (Logger.LOG_PERSONAL_INFORMATION) {
         Logger.pii(LOG_TAG, "Successful upload with id " + id + " obsoleting "
             + oldIds.size() + " old records reported at " + localTime + "; next upload at " + next + ".");
       } else {
         Logger.info(LOG_TAG, "Successful upload obsoleting " + oldIds.size()
             + " old records reported at " + localTime + "; next upload at " + next + ".");
       }
@@ -188,16 +201,17 @@ public class SubmissionPolicy {
         tracker.removeObsoleteId(id);
       } else {
         tracker.decrementObsoleteIdAttempts(oldIds);
       }
       editor
         .setNextSubmission(next)
         .setLastUploadFailed(localTime)
         .setCurrentDayFailureCount(0)
+        .clearCurrentDayResetTime() // Set again on the next submission's first upload attempt.
         .commit();
       Logger.warn(LOG_TAG, "Hard failure reported at " + localTime + ": " + reason + " Next upload at " + next + ".", e);
     }
 
     @Override
     public void onSoftFailure(long localTime, String id, String reason, Exception e) {
       int failuresToday = getCurrentDayFailureCount();
       Logger.warn(LOG_TAG, "Soft failure reported at " + localTime + ": " + reason + " Previously failed " + failuresToday + " time(s) today.");
@@ -314,16 +328,21 @@ public class SubmissionPolicy {
     return getSharedPreferences().getLong(HealthReportConstants.PREF_NEXT_SUBMISSION, -1);
   }
 
   // Authoritative.
   public int getCurrentDayFailureCount() {
     return getSharedPreferences().getInt(HealthReportConstants.PREF_CURRENT_DAY_FAILURE_COUNT, 0);
   }
 
+  // Authoritative.
+  public long getCurrentDayResetTime() {
+    return getSharedPreferences().getLong(HealthReportConstants.PREF_CURRENT_DAY_RESET_TIME, -1);
+  }
+
   /**
    * To avoid writing to disk multiple times, we encapsulate writes in a
    * helper class. Be sure to call <code>commit</code> to flush to disk!
    */
   protected Editor editor() {
     return new Editor(getSharedPreferences().edit());
   }
 
@@ -351,16 +370,28 @@ public class SubmissionPolicy {
     }
 
     // Authoritative.
     public Editor setCurrentDayFailureCount(int failureCount) {
       editor.putInt(HealthReportConstants.PREF_CURRENT_DAY_FAILURE_COUNT, failureCount);
       return this;
     }
 
+    // Authoritative.
+    public Editor setCurrentDayResetTime(long resetTime) {
+      editor.putLong(HealthReportConstants.PREF_CURRENT_DAY_RESET_TIME, resetTime);
+      return this;
+    }
+
+    // Authoritative.
+    public Editor clearCurrentDayResetTime() {
+      editor.putLong(HealthReportConstants.PREF_CURRENT_DAY_RESET_TIME, -1);
+      return this;
+    }
+
     // Forensics only.
     public Editor setLastUploadRequested(long localTime) {
       editor.putLong(HealthReportConstants.PREF_LAST_UPLOAD_REQUESTED, localTime);
       return this;
     }
 
     // Forensics only.
     public Editor setLastUploadSucceeded(long localTime) {
--- a/mobile/android/config/mozconfigs/common
+++ b/mobile/android/config/mozconfigs/common
@@ -39,8 +39,14 @@ ac_add_options --enable-update-channel=$
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 # Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
+
+HOST_CC="/tools/gcc-4.7.2-0moz1/bin/gcc"
+HOST_CXX="/tools/gcc-4.7.2-0moz1/bin/g++"
+
+# Avoid dependency on libstdc++ 4.7
+ac_add_options --enable-stdcxx-compat
--- a/mobile/android/locales/en-US/chrome/browser.properties
+++ b/mobile/android/locales/en-US/chrome/browser.properties
@@ -160,16 +160,19 @@ contextmenu.bookmarkLink=Bookmark Link
 contextmenu.copyEmailAddress=Copy Email Address
 contextmenu.shareEmailAddress=Share Email Address
 contextmenu.copyPhoneNumber=Copy Phone Number
 contextmenu.sharePhoneNumber=Share Phone Number
 contextmenu.changeInputMethod=Select Input Method
 contextmenu.fullScreen=Full Screen
 contextmenu.copyImageLocation=Copy Image Location
 contextmenu.shareImage=Share Image
+# LOCALIZATION NOTE (contextmenu.search):
+# The label of the contextmenu item which allows you to search with your default search engine for
+# the text you have selected. %S is the name of the search engine. For example, "Google".
 contextmenu.search=%S Search
 contextmenu.saveImage=Save Image
 contextmenu.setWallpaper=Set as Wallpaper
 contextmenu.addSearchEngine=Add Search Engine
 contextmenu.playMedia=Play
 contextmenu.pauseMedia=Pause
 contextmenu.shareMedia=Share Video
 contextmenu.showControls2=Show Controls
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/action/process_install_manifest.py
@@ -0,0 +1,41 @@
+# 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/.
+
+from __future__ import print_function, unicode_literals
+
+import argparse
+from mozpack.copier import FileCopier
+from mozpack.manifests import InstallManifest
+
+
+COMPLETE = 'From {dest}: Kept {existing} existing; Added/updated {updated}; ' \
+    'Removed {rm_files} files and {rm_dirs} directories.'
+
+
+def process_manifest(destdir, *paths):
+    manifest = InstallManifest()
+    for path in paths:
+        manifest |= InstallManifest(path=path)
+
+    copier = FileCopier()
+    manifest.populate_registry(copier)
+    return copier.copy(destdir)
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(
+        description='Process install manifest files.')
+
+    parser.add_argument('destdir', help='Destination directory.')
+    parser.add_argument('manifests', nargs='+', help='Path to manifest file(s).')
+
+    args = parser.parse_args()
+
+    result = process_manifest(args.destdir, *args.manifests)
+
+    print(COMPLETE.format(dest=args.destdir,
+        existing=result.existing_files_count,
+        updated=result.updated_files_count,
+        rm_files=result.removed_files_count,
+        rm_dirs=result.removed_directories_count))
--- a/toolkit/components/jsdownloads/src/DownloadCore.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadCore.jsm
@@ -184,16 +184,33 @@ Download.prototype = {
   currentBytes: 0,
 
   /**
    * This can be set to a function that is called after other properties change.
    */
   onchange: null,
 
   /**
+   * This tells if the user has chosen to open/run the downloaded file after
+   * download has completed.
+   */
+  launchWhenSucceeded: false,
+
+  /**
+   * This represents the MIME type of the download.
+   */
+  contentType: null,
+
+  /**
+   * This indicates the path of the application to be used to launch the file,
+   * or null if the file should be launched with the default application.
+   */
+  launcherPath: null,
+
+  /**
    * Raises the onchange notification.
    */
   _notifyChange: function D_notifyChange() {
     try {
       if (this.onchange) {
         this.onchange();
       }
     } catch (ex) {
@@ -269,16 +286,37 @@ Download.prototype = {
     // it comes in late from a download attempt that was replaced by a new one.
     function DS_setProgressBytes(aCurrentBytes, aTotalBytes)
     {
       if (this._currentAttempt == currentAttempt || !this._currentAttempt) {
         this._setBytes(aCurrentBytes, aTotalBytes);
       }
     }
 
+    // This function propragates download properties from the DownloadSaver
+    // object, unless it comes in late from a download attempt that was
+    // replaced by a new one.
+    function DS_setDownloadProperties(aOptions) {
+      if (this._currentAttempt && this._currentAttempt != currentAttempt) {
+        return;
+      }
+
+      let changeMade = false;
+
+      if ("contentType" in aOptions &&
+          this.contentType != aOptions.contentType) {
+        this.contentType = aOptions.contentType;
+        changeMade = true;
+      }
+
+      if (changeMade) {
+        this._notifyChange();
+      }
+    }
+
     // Now that we stored the promise in the download object, we can start the
     // task that will actually execute the download.
     deferAttempt.resolve(Task.spawn(function task_D_start() {
       // Wait upon any pending cancellation request.
       if (this._promiseCanceled) {
         yield this._promiseCanceled;
       }
 
@@ -287,17 +325,18 @@ Download.prototype = {
         let error = new DownloadError(Cr.NS_ERROR_FAILURE, "Download blocked.");
         error.becauseBlocked = true;
         error.becauseBlockedByParentalControls = true;
         throw error;
       }
 
       try {
         // Execute the actual download through the saver object.
-        yield this.saver.execute(DS_setProgressBytes.bind(this));
+        yield this.saver.execute(DS_setProgressBytes.bind(this),
+                                 DS_setDownloadProperties.bind(this));
 
         // Update the status properties for a successful download.
         this.progress = 100;
         this.succeeded = true;
       } catch (ex) {
         // Fail with a generic status code on cancellation, so that the caller
         // is forced to actually check the status properties to see if the
         // download was canceled or failed because of other reasons.
@@ -317,26 +356,71 @@ Download.prototype = {
 
         // Update the status properties, unless a new attempt already started.
         if (this._currentAttempt == currentAttempt || !this._currentAttempt) {
           this._currentAttempt = null;
           this.stopped = true;
           this._notifyChange();
           if (this.succeeded) {
             this._deferSucceeded.resolve();
+
+            if (this.launchWhenSucceeded) {
+              this.launch().then(null, Cu.reportError);
+            }
           }
         }
       }
     }.bind(this)));
 
     // Notify the new download state before returning.
     this._notifyChange();
     return this._currentAttempt;
   },
 
+  /*
+   * Launches the file after download has completed. This can open
+   * the file with the default application for the target MIME type
+   * or file extension, or with a custom application if launcherPath
+   * is set.
+   *
+   * @return {Promise}
+   * @resolves When the instruction to launch the file has been
+   *           successfully given to the operating system. Note that
+   *           the OS might still take a while until the file is actually
+   *           launched.
+   * @rejects  JavaScript exception if there was an error trying to launch
+   *           the file.
+   */
+  launch: function() {
+    if (!this.succeeded) {
+      return Promise.reject(
+        new Error("launch can only be called if the download succeeded")
+      );
+    }
+
+    return DownloadIntegration.launchDownload(this);
+  },
+
+  /*
+   * Shows the folder containing the target file, or where the target file
+   * will be saved. This may be called at any time, even if the download
+   * failed or is currently in progress.
+   *
+   * @return {Promise}
+   * @resolves When the instruction to open the containing folder has been
+   *           successfully given to the operating system. Note that
+   *           the OS might still take a while until the folder is actually
+   *           opened.
+   * @rejects  JavaScript exception if there was an error trying to open
+   *           the containing folder.
+   */
+  showContainingDirectory: function D_showContainingDirectory() {
+    return DownloadIntegration.showContainingDirectory(this.target.path);
+  },
+
   /**
    * When a request to cancel the download is received, contains a promise that
    * will be resolved when the cancellation request is processed.  When the
    * request is processed, this property becomes null again.
    */
   _promiseCanceled: null,
 
   /**
@@ -450,16 +534,28 @@ Download.prototype = {
     // is an object instead of a simple string, we can't simplify it because we
     // need to persist all its properties, not only "type".  This may happen for
     // savers of type "copy" as well as other types.
     let saver = this.saver.toSerializable();
     if (saver !== "copy") {
       serializable.saver = saver;
     }
 
+    if (this.launcherPath) {
+      serializable.launcherPath = this.launcherPath;
+    }
+
+    if (this.launchWhenSucceeded) {
+      serializable.launchWhenSucceeded = true;
+    }
+
+    if (this.contentType) {
+      serializable.contentType = this.contentType;
+    }
+
     return serializable;
   },
 };
 
 /**
  * Creates a new Download object from a serializable representation.  This
  * function is used by the createDownload method of Downloads.jsm when a new
  * Download object is requested, thus some properties may refer to live objects
@@ -492,16 +588,29 @@ Download.fromSerializable = function (aS
     download.target = DownloadTarget.fromSerializable(aSerializable.target);
   }
   if ("saver" in aSerializable) {
     download.saver = DownloadSaver.fromSerializable(aSerializable.saver);
   } else {
     download.saver = DownloadSaver.fromSerializable("copy");
   }
   download.saver.download = download;
+
+  if ("launchWhenSucceeded" in aSerializable) {
+    download.launchWhenSucceeded = !!aSerializable.launchWhenSucceeded;
+  }
+
+  if ("contentType" in aSerializable) {
+    download.contentType = aSerializable.contentType;
+  }
+
+  if ("launcherPath" in aSerializable) {
+    download.launcherPath = aSerializable.launcherPath;
+  }
+
   return download;
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 //// DownloadSource
 
 /**
  * Represents the source of a download, for example a document or an URI.
@@ -728,22 +837,28 @@ DownloadSaver.prototype = {
   /**
    * Executes the download.
    *
    * @param aSetProgressBytesFn
    *        This function may be called by the saver to report progress. It
    *        takes two arguments: the first is the number of bytes transferred
    *        until now, the second is the total number of bytes to be
    *        transferred, or -1 if unknown.
+   * @parem aSetPropertiesFn
+   *        This function may be called by the saver to report information
+   *        about new download properties discovered by the saver during the
+   *        download process. It takes an object where the keys represents
+   *        the names of the properties to set, and the value represents the
+   *        value to set.
    *
    * @return {Promise}
    * @resolves When the download has finished successfully.
    * @rejects JavaScript exception if the download failed.
    */
-  execute: function DS_execute(aSetProgressBytesFn)
+  execute: function DS_execute(aSetProgressBytesFn, aSetPropertiesFn)
   {
     throw new Error("Not implemented.");
   },
 
   /**
    * Cancels the download.
    */
   cancel: function DS_cancel()
@@ -803,17 +918,17 @@ DownloadCopySaver.prototype = {
   /**
    * BackgroundFileSaver object currently handling the download.
    */
   _backgroundFileSaver: null,
 
   /**
    * Implements "DownloadSaver.execute".
    */
-  execute: function DCS_execute(aSetProgressBytesFn)
+  execute: function DCS_execute(aSetProgressBytesFn, aSetPropertiesFn)
   {
     let deferred = Promise.defer();
     let download = this.download;
 
     // Create the object that will save the file in a background thread.
     let backgroundFileSaver = new BackgroundFileSaverStreamListener();
     try {
       // When the operation completes, reflect the status in the promise
@@ -868,16 +983,17 @@ DownloadCopySaver.prototype = {
         {
           backgroundFileSaver.onStartRequest(aRequest, aContext);
 
           // Ensure we report the value of "Content-Length", if available, even
           // if the download doesn't generate any progress events later.
           if (aRequest instanceof Ci.nsIChannel &&
               aRequest.contentLength >= 0) {
             aSetProgressBytesFn(0, aRequest.contentLength);
+            aSetPropertiesFn({ contentType: aRequest.contentType });
           }
         },
         onStopRequest: function DCSE_onStopRequest(aRequest, aContext,
                                                    aStatusCode)
         {
           try {
             backgroundFileSaver.onStopRequest(aRequest, aContext, aStatusCode);
           } finally {
--- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
@@ -34,19 +34,28 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
                                   "resource://gre/modules/commonjs/sdk/core/promise.js");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
                                   "resource://gre/modules/Task.jsm");
-XPCOMUtils.defineLazyServiceGetter(this, "env",
+XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
+                                  "resource://gre/modules/NetUtil.jsm");
+XPCOMUtils.defineLazyServiceGetter(this, "gEnvironment",
                                    "@mozilla.org/process/environment;1",
                                    "nsIEnvironment");
+XPCOMUtils.defineLazyServiceGetter(this, "gMIMEService",
+                                   "@mozilla.org/mime;1",
+                                   "nsIMIMEService");
+XPCOMUtils.defineLazyServiceGetter(this, "gExternalProtocolService",
+                                   "@mozilla.org/uriloader/external-protocol-service;1",
+                                   "nsIExternalProtocolService");
+
 XPCOMUtils.defineLazyGetter(this, "gParentalControlsService", function() {
   if ("@mozilla.org/parental-controls-service;1" in Cc) {
     return Cc["@mozilla.org/parental-controls-service;1"]
       .createInstance(Ci.nsIParentalControlsService);
   }
   return null;
 });
 
@@ -63,16 +72,19 @@ XPCOMUtils.defineLazyGetter(this, "gStri
  * example the global prompts on shutdown.
  */
 this.DownloadIntegration = {
   // For testing only
   testMode: false,
   dontLoad: false,
   dontCheckParentalControls: false,
   shouldBlockInTest: false,
+  dontOpenFileAndFolder: false,
+  _deferTestOpenFile: null,
+  _deferTestShowDir: null,
 
   /**
    * Main DownloadStore object for loading and saving the list of persistent
    * downloads, or null if the download list was never requested and thus it
    * doesn't need to be persisted.
    */
   _store: null,
 
@@ -140,17 +152,17 @@ this.DownloadIntegration = {
       // Linux distros do) neither has a working $HOME/Desktop folder
       // for us to fallback into, "$HOME/MyDocs/.documents/" is the folder
       // we found most appropriate to be the default target folder for
       // downloads on the platform.
       directory = this._getDirectory("XDGDocs");
 #elifdef ANDROID
       // Android doesn't have a $HOME directory, and by default we only have
       // write access to /data/data/org.mozilla.{$APP} and /sdcard
-      let directoryPath = env.get("DOWNLOADS_DIRECTORY");
+      let directoryPath = gEnvironment.get("DOWNLOADS_DIRECTORY");
       if (!directoryPath