Merge m-c to birch.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 03 Jun 2013 07:44:41 -0400
changeset 145257 1ee64bcc673cee097010b3605c1d04fab29c15a1
parent 145256 81b59ee890a7a634915e330c8204a6de40bf6b3f (current diff)
parent 145227 198e38876f7e06d49be862710f76881f79abf1d7 (diff)
child 145258 a3fcf6de63880602780b741967f3ec202f40cda6
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone24.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.
dom/base/nsBarProps.cpp
dom/base/nsBarProps.h
dom/interfaces/base/nsIDOMBarProp.idl
--- a/browser/base/content/browser-fullScreen.js
+++ b/browser/base/content/browser-fullScreen.js
@@ -105,21 +105,23 @@ var FullScreen = {
     }
   },
 
   enterDomFullscreen : function(event) {
     if (!document.mozFullScreen)
       return;
 
     // However, if we receive a "MozEnteredDomFullScreen" event for a document
-    // which is not a subdocument of the currently selected tab, we know that
-    // we've switched tabs since the request to enter full-screen was made,
-    // so we should exit full-screen since the "full-screen document" isn't
-    // acutally visible.
-    if (event.target.defaultView.top != gBrowser.contentWindow) {
+    // which is not a subdocument of a currently active (ie. visible) browser
+    // or iframe, we know that we've switched to a different frame since the
+    // request to enter full-screen was made, so we should exit full-screen
+    // since the "full-screen document" isn't acutally visible.
+    if (!event.target.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
+                                 .getInterface(Ci.nsIWebNavigation)
+                                 .QueryInterface(Ci.nsIDocShell).isActive) {
       document.mozCancelFullScreen();
       return;
     }
 
     let focusManager = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
     if (focusManager.activeWindow != window) {
       // The top-level window has lost focus since the request to enter
       // full-screen was made. Cancel full-screen.
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -37,22 +37,16 @@ SocialUI = {
     Services.obs.addObserver(this, "social:provider-set", false);
     Services.obs.addObserver(this, "social:providers-changed", false);
 
     Services.prefs.addObserver("social.sidebar.open", this, false);
     Services.prefs.addObserver("social.toast-notifications.enabled", this, false);
 
     gBrowser.addEventListener("ActivateSocialFeature", this._activationEventHandler.bind(this), true, true);
 
-    // Called when we enter DOM full-screen mode.
-    window.addEventListener("mozfullscreenchange", function () {
-      SocialSidebar.update();
-      SocialChatBar.update();
-    });
-
     SocialChatBar.init();
     SocialMark.init();
     SocialShare.init();
     SocialMenu.init();
     SocialToolbar.init();
     SocialSidebar.init();
 
     if (!Social.initialized) {
@@ -374,17 +368,17 @@ SocialChatBar = {
     return true;
   },
   update: function() {
     let command = document.getElementById("Social:FocusChat");
     if (!this.isAvailable) {
       this.chatbar.removeAll();
       this.chatbar.hidden = command.hidden = true;
     } else {
-      this.chatbar.hidden = command.hidden = document.mozFullScreen;
+      this.chatbar.hidden = command.hidden = false;
     }
     command.setAttribute("disabled", command.hidden ? "true" : "false");
   },
   focus: function SocialChatBar_focus() {
     this.chatbar.focus();
   }
 }
 
@@ -445,18 +439,24 @@ DynamicResizeWatcher.prototype = {
   }
 }
 
 SocialFlyout = {
   get panel() {
     return document.getElementById("social-flyout-panel");
   },
 
+  get iframe() {
+    if (!this.panel.firstChild)
+      this._createFrame();
+    return this.panel.firstChild;
+  },
+
   dispatchPanelEvent: function(name) {
-    let doc = this.panel.firstChild.contentDocument;
+    let doc = this.iframe.contentDocument;
     let evt = doc.createEvent("CustomEvent");
     evt.initCustomEvent(name, true, true, {});
     doc.documentElement.dispatchEvent(evt);
   },
 
   _createFrame: function() {
     let panel = this.panel;
     if (!SocialUI.enabled || panel.firstChild)
@@ -467,39 +467,35 @@ SocialFlyout = {
     iframe.setAttribute("class", "social-panel-frame");
     iframe.setAttribute("flex", "1");
     iframe.setAttribute("tooltip", "aHTMLTooltip");
     iframe.setAttribute("origin", Social.provider.origin);
     panel.appendChild(iframe);
   },
 
   setFlyoutErrorMessage: function SF_setFlyoutErrorMessage() {
-    let iframe = this.panel.firstChild;
-    if (!iframe)
-      return;
-
-    iframe.removeAttribute("src");
-    iframe.webNavigation.loadURI("about:socialerror?mode=compactInfo", null, null, null, null);
-    sizeSocialPanelToContent(this.panel, iframe);
+    this.iframe.removeAttribute("src");
+    this.iframe.webNavigation.loadURI("about:socialerror?mode=compactInfo", null, null, null, null);
+    sizeSocialPanelToContent(this.panel, this.iframe);
   },
 
   unload: function() {
     let panel = this.panel;
     panel.hidePopup();
     if (!panel.firstChild)
       return
     let iframe = panel.firstChild;
     if (iframe.socialErrorListener)
       iframe.socialErrorListener.remove();
     panel.removeChild(iframe);
   },
 
   onShown: function(aEvent) {
     let panel = this.panel;
-    let iframe = panel.firstChild;
+    let iframe = this.iframe;
     this._dynamicResizer = new DynamicResizeWatcher();
     iframe.docShell.isActive = true;
     iframe.docShell.isAppTab = true;
     if (iframe.contentDocument.readyState == "complete") {
       this._dynamicResizer.start(panel, iframe);
       this.dispatchPanelEvent("socialFrameShow");
     } else {
       // first time load, wait for load and dispatch after load
@@ -513,65 +509,72 @@ SocialFlyout = {
         }, 0);
       }, true);
     }
   },
 
   onHidden: function(aEvent) {
     this._dynamicResizer.stop();
     this._dynamicResizer = null;
-    this.panel.firstChild.docShell.isActive = false;
+    this.iframe.docShell.isActive = false;
     this.dispatchPanelEvent("socialFrameHide");
   },
 
+  load: function(aURL, cb) {
+    if (!Social.provider)
+      return;
+
+    this.panel.hidden = false;
+    let iframe = this.iframe;
+    // same url with only ref difference does not cause a new load, so we
+    // want to go right to the callback
+    let src = iframe.contentDocument && iframe.contentDocument.documentURIObject;
+    if (!src || !src.equalsExceptRef(Services.io.newURI(aURL, null, null))) {
+      iframe.addEventListener("load", function documentLoaded() {
+        iframe.removeEventListener("load", documentLoaded, true);
+        cb();
+      }, true);
+      // Force a layout flush by calling .clientTop so
+      // that the docShell of this frame is created
+      iframe.clientTop;
+      Social.setErrorListener(iframe, SocialFlyout.setFlyoutErrorMessage.bind(SocialFlyout))
+      iframe.setAttribute("src", aURL);
+    } else {
+      // we still need to set the src to trigger the contents hashchange event
+      // for ref changes
+      iframe.setAttribute("src", aURL);
+      cb();
+    }
+  },
+
   open: function(aURL, yOffset, aCallback) {
     // Hide any other social panels that may be open.
     document.getElementById("social-notification-panel").hidePopup();
 
     if (!SocialUI.enabled)
       return;
     let panel = this.panel;
-    if (!panel.firstChild)
-      this._createFrame();
-    panel.hidden = false;
-    let iframe = panel.firstChild;
+    let iframe = this.iframe;
 
-    let src = iframe.getAttribute("src");
-    if (src != aURL) {
-      iframe.addEventListener("load", function documentLoaded() {
-        iframe.removeEventListener("load", documentLoaded, true);
-        if (aCallback) {
-          try {
-            aCallback(iframe.contentWindow);
-          } catch(e) {
-            Cu.reportError(e);
-          }
+    this.load(aURL, function() {
+      sizeSocialPanelToContent(panel, iframe);
+      let anchor = document.getElementById("social-sidebar-browser");
+      if (panel.state == "open") {
+        panel.moveToAnchor(anchor, "start_before", 0, yOffset, false);
+      } else {
+        panel.openPopup(anchor, "start_before", 0, yOffset, false, false);
+      }
+      if (aCallback) {
+        try {
+          aCallback(iframe.contentWindow);
+        } catch(e) {
+          Cu.reportError(e);
         }
-      }, true);
-      iframe.setAttribute("src", aURL);
-    }
-    else if (aCallback) {
-      try {
-        aCallback(iframe.contentWindow);
-      } catch(e) {
-        Cu.reportError(e);
       }
-    }
-
-    sizeSocialPanelToContent(panel, iframe);
-    let anchor = document.getElementById("social-sidebar-browser");
-    if (panel.state == "open") {
-      panel.moveToAnchor(anchor, "start_before", 0, yOffset, false);
-    } else {
-      panel.openPopup(anchor, "start_before", 0, yOffset, false, false);
-      // Force a layout flush by calling .clientTop so
-      // that the docShell of this frame is created
-      panel.firstChild.clientTop;
-      Social.setErrorListener(iframe, this.setFlyoutErrorMessage.bind(this))
-    }
+    });
   }
 }
 
 SocialShare = {
   // Called once, after window load, when the Social.provider object is initialized
   init: function() {},
 
   get panel() {
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -403,16 +403,17 @@ window[chromehidden~="toolbar"] toolbar:
 }
 
 #full-screen-warning-container {
   position: fixed;
   top: 0;
   left: 0;
   width: 100%;
   height: 100%;
+  z-index: 2147483647 !important;
 }
 
 #full-screen-warning-container[fade-warning-out] {
   transition-property: opacity !important;
   transition-duration: 500ms !important;
   opacity: 0.0;
 }
 
@@ -656,8 +657,42 @@ chatbox[minimized="true"] {
   height: 20px; /* CHAT_WIDTH_MINIMIZED in socialchat.xml */
 }
 
 chatbar {
   -moz-binding: url("chrome://browser/content/socialchat.xml#chatbar");
   height: 0;
   max-height: 0;
 }
+
+/* full screen chat window support */
+chatbar:-moz-full-screen-ancestor,
+chatbox:-moz-full-screen-ancestor  {
+  border: none;
+  position: fixed !important;
+  top: 0 !important;
+  left: 0 !important;
+  right: 0 !important;
+  bottom: 0 !important;
+  width: 100% !important;
+  height: 100% !important;
+  margin: 0 !important;
+  min-width: 0 !important;
+  max-width: none !important;
+  min-height: 0 !important;
+  max-height: none !important;
+  -moz-box-sizing: border-box !important; 
+}
+
+/* hide chat chrome when chat is fullscreen */
+chatbox:-moz-full-screen-ancestor > .chat-titlebar {
+  display: none;
+}
+
+/* hide chatbar if browser tab is fullscreen */
+*:-moz-full-screen-ancestor chatbar:not(:-moz-full-screen-ancestor) {
+  display: none;
+}
+
+/* hide sidebar when fullscreen */
+*:-moz-full-screen-ancestor #social-sidebar-box:not(:-moz-full-screen-ancestor) {
+  display: none;
+}
--- a/browser/base/content/pageinfo/permissions.js
+++ b/browser/base/content/pageinfo/permissions.js
@@ -297,29 +297,29 @@ function clearPluginPermissionTemplate()
 }
 
 function initPluginsRow() {
   let pluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
   let tags = pluginHost.getPluginTags().filter(function(aTag) {
     let mimeTypes = aTag.getMimeTypes();
     if (mimeTypes.length < 1)
       return false;
-    let mimeType = mimeTypes[0].type;
+    let mimeType = mimeTypes[0];
     return (!aTag.disabled && pluginHost.isPluginClickToPlayForType(mimeType));
   });
 
   tags.sort(function(tagA, tagB) {
     let nameA = makeNicePluginName(tagA.name);
     let nameB = makeNicePluginName(tagB.name);
     return nameA < nameB ? -1 : (nameA == nameB ? 0 : 1);
   });
 
   let permissionEntries = [];
   for (let plugin of tags) {
-    let mimeType = plugin.getMimeTypes()[0].type;
+    let mimeType = plugin.getMimeTypes()[0];
     let permString = pluginHost.getPermissionStringForType(mimeType);
     let pluginName = makeNicePluginName(plugin.name)
     let permEntry = fillInPluginPermissionTemplate(pluginName, permString);
     permissionEntries.push(permEntry);
   }
 
   let permPluginsRow = document.getElementById("permPluginsRow");
   clearPluginPermissionTemplate();
--- a/browser/base/content/test/social/browser_social_chatwindow.js
+++ b/browser/base/content/test/social/browser_social_chatwindow.js
@@ -100,57 +100,16 @@ var tests = {
             is(chats.selectedChat, null, "should only have been one chat open");
             port.close();
             next();
           }
       }
     }
     port.postMessage({topic: "test-init", data: { id: 1 }});
   },
-  // In this case the *worker* opens a chat (so minimized is specified).
-  // The worker then makes the same call again - as that second call also
-  // specifies "minimized" the chat should *not* be restored.
-  testWorkerChatWindowMinimized: function(next) {
-    const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html";
-    let port = Social.provider.getWorkerPort();
-    let seen_opened = false;
-    ok(port, "provider has a port");
-    port.postMessage({topic: "test-init"});
-    port.onmessage = function (e) {
-      let topic = e.data.topic;
-      switch (topic) {
-        case "got-chatbox-message":
-          ok(true, "got a chat window opened");
-          let chats = document.getElementById("pinnedchats");
-          if (!seen_opened) {
-            // first time we got the opened message, so minimize the chat then
-            // re-request the same chat to be opened - we should get the
-            // message again and the chat should be restored.
-            ok(chats.selectedChat.minimized, "chatbox from worker opened as minimized");
-            seen_opened = true;
-            port.postMessage({topic: "test-worker-chat", data: chatUrl});
-            // Sadly there is no notification we can use to know the chat was
-            // re-opened :(  So we ask the chat window to "ping" us - by then
-            // the second request should have made it.
-            chats.selectedChat.iframe.contentWindow.wrappedJSObject.pingWorker();
-          } else {
-            // This is the second time we've seen this message - there should
-            // be exactly 1 chat open and it should still be minimized.
-            let chats = document.getElementById("pinnedchats");
-            ok(chats.selectedChat.minimized, "chat still minimized")
-            chats.selectedChat.close();
-            is(chats.selectedChat, null, "should only have been one chat open");
-            port.close();
-            next();
-          }
-          break;
-      }
-    }
-    port.postMessage({topic: "test-worker-chat", data: chatUrl});
-  },
   testManyChats: function(next) {
     // open enough chats to overflow the window, then check
     // if the menupopup is visible
     let port = Social.provider.getWorkerPort();
     let chats = document.getElementById("pinnedchats");
     ok(port, "provider has a port");
     ok(chats.menupopup.parentNode.collapsed, "popup nub collapsed at start");
     port.postMessage({topic: "test-init"});
@@ -184,36 +143,37 @@ var tests = {
           next();
           break;
       }
     }
     maybeOpenAnother();
   },
   testWorkerChatWindow: function(next) {
     const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html";
+    let chats = document.getElementById("pinnedchats");
     let port = Social.provider.getWorkerPort();
     ok(port, "provider has a port");
     port.postMessage({topic: "test-init"});
     port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "got-chatbox-message":
           ok(true, "got a chat window opened");
-          let chats = document.getElementById("pinnedchats");
-          ok(chats.selectedChat.minimized, "chatbox from worker opened as minimized");
+          ok(chats.selectedChat, "chatbox from worker opened");
           while (chats.selectedChat) {
             chats.selectedChat.close();
           }
           ok(!chats.selectedChat, "chats are all closed");
           gURLsNotRemembered.push(chatUrl);
           port.close();
           next();
           break;
       }
     }
+    ok(!chats.selectedChat, "chats are all closed");
     port.postMessage({topic: "test-worker-chat", data: chatUrl});
   },
   testCloseSelf: function(next) {
     let chats = document.getElementById("pinnedchats");
     let port = Social.provider.getWorkerPort();
     ok(port, "provider has a port");
     port.onmessage = function (e) {
       let topic = e.data.topic;
--- a/browser/base/content/test/social/browser_social_chatwindowfocus.js
+++ b/browser/base/content/test/social/browser_social_chatwindowfocus.js
@@ -162,26 +162,25 @@ var tests = {
       waitForCondition(function() isChatFocused(SocialChatBar.chatbar.selectedChat),
                        function() {
         is(SocialChatBar.chatbar.selectedChat, SocialChatBar.chatbar.firstElementChild, "chat is selected");
         next();
       }, "chat should be focused");
     });
   },
 
-  // Open a chat via the worker - it will open minimized and not have focus.
+  // Open a chat via the worker - it will open and not have focus.
   // Then open the same chat via a sidebar message - it will be restored but
   // should still not have grabbed focus.
   testNoFocusOnAutoRestore: function(next) {
     const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html?id=1";
     let chatbar = SocialChatBar.chatbar;
     startTestAndWaitForSidebar(function(port) {
       openChatViaWorkerMessage(port, chatUrl, function() {
         is(chatbar.childElementCount, 1, "exactly 1 chat open");
-        ok(chatbar.firstElementChild.minimized, "chat is minimized");
         // bug 865086 opening minimized still sets the window as selected
         todo(chatbar.selectedChat != chatbar.firstElementChild, "chat is not selected");
         ok(isTabFocused(), "tab should be focused");
         openChatViaSidebarMessage(port, {stealFocus: 1, id: 1}, function() {
           is(chatbar.childElementCount, 1, "still 1 chat open");
           ok(!chatbar.firstElementChild.minimized, "chat no longer minimized");
           // bug 865086 because we marked it selected on open, it still is
           todo(chatbar.selectedChat != chatbar.firstElementChild, "chat is not selected");
--- a/browser/base/content/test/social/browser_social_flyout.js
+++ b/browser/base/content/test/social/browser_social_flyout.js
@@ -15,16 +15,20 @@ function test() {
   runSocialTestWithProvider(manifest, function (finishcb) {
     runSocialTests(tests, undefined, undefined, finishcb);
   });
 }
 
 var tests = {
   testOpenCloseFlyout: function(next) {
     let panel = document.getElementById("social-flyout-panel");
+    panel.addEventListener("popupshowing", function onShowing() {
+      panel.removeEventListener("popupshowing", onShowing);
+      is(panel.firstChild.contentDocument.readyState, "complete", "panel is loaded prior to showing");
+    });
     let port = Social.provider.getWorkerPort();
     ok(port, "provider has a port");
     port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "got-sidebar-message":
           port.postMessage({topic: "test-flyout-open"});
           break;
--- a/browser/metro/base/content/appbar.js
+++ b/browser/metro/base/content/appbar.js
@@ -1,102 +1,97 @@
 /* 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/. */
 "use strict";
 
 var Appbar = {
   get consoleButton() { return document.getElementById('console-button'); },
   get jsShellButton() { return document.getElementById('jsshell-button'); },
-  get zoomInButton()  { return document.getElementById('zoomin-button'); },
-  get zoomOutButton() { return document.getElementById('zoomout-button'); },
   get starButton()    { return document.getElementById('star-button'); },
   get pinButton()     { return document.getElementById('pin-button'); },
   get moreButton()    { return document.getElementById('more-button'); },
 
   // track selected/active richgrid/tilegroup - the context for contextual action buttons
   activeTileset: null,
 
   init: function Appbar_init() {
     window.addEventListener('MozContextUIShow', this);
     window.addEventListener('MozContextUIDismiss', this);
     window.addEventListener('MozAppbarDismiss', this);
     Elements.contextappbar.addEventListener('MozAppbarShowing', this, false);
     Elements.contextappbar.addEventListener('MozAppbarDismissing', this, false);
-    window.addEventListener('MozPrecisePointer', this, false);
-    window.addEventListener('MozImprecisePointer', this, false);
     window.addEventListener('MozContextActionsChange', this, false);
     Elements.browsers.addEventListener('URLChanged', this, true);
     Elements.tabList.addEventListener('TabSelect', this, true);
     Elements.panelUI.addEventListener('ToolPanelShown', this, false);
     Elements.panelUI.addEventListener('ToolPanelHidden', this, false);
 
     this._updateDebugButtons();
-    this._updateZoomButtons();
 
     // tilegroup selection events for all modules get bubbled up
     window.addEventListener("selectionchange", this, false);
   },
 
   handleEvent: function Appbar_handleEvent(aEvent) {
     switch (aEvent.type) {
+      case 'URLChanged':
+      case 'TabSelect':
+        this.update();
+        Elements.navbar.dismiss();
+        Elements.contextappbar.dismiss();
+        break;
       case 'MozContextUIShow':
         Elements.navbar.show();
         break;
       case 'MozAppbarDismiss':
       case 'MozContextUIDismiss':
-      case 'URLChanged':
-      case 'TabSelect':
       case 'ToolPanelShown':
       case 'ToolPanelHidden':
         Elements.navbar.dismiss();
         Elements.contextappbar.dismiss();
         break;
       case 'MozAppbarShowing':
-        this._updatePinButton();
-        this._updateStarButton();
         break;
       case 'MozAppbarDismissing':
         if (this.activeTileset) {
           this.activeTileset.clearSelection();
         }
         this.clearContextualActions();
         this.activeTileset = null;
         break;
-      case 'MozPrecisePointer':
-      case 'MozImprecisePointer':
-        this._updateZoomButtons();
-        break;
       case 'MozContextActionsChange':
         let actions = aEvent.actions;
         // could transition in old, new buttons?
         this.showContextualActions(actions);
         break;
       case "selectionchange":
         let nodeName = aEvent.target.nodeName;
         if ('richgrid' === nodeName) {
           this._onTileSelectionChanged(aEvent);
         }
         break;
     }
   },
 
+  /*
+   * Called from various places when the visible content
+   * has changed such that button states may need to be
+   * updated.
+   */
+  update: function update() {
+    this._updatePinButton();
+    this._updateStarButton();
+  },
+
   onDownloadButton: function() {
     PanelUI.show("downloads-container");
     ContextUI.dismiss();
   },
 
-  onZoomOutButton: function() {
-    Browser.zoom(1);
-  },
-
-  onZoomInButton: function() {
-    Browser.zoom(-1);
-  },
-
   onPinButton: function() {
     if (this.pinButton.checked) {
       Browser.pinSite();
     } else {
       Browser.unpinSite();
     }
   },
 
@@ -264,14 +259,9 @@ var Appbar = {
       this.starButton.checked = isStarred;
     }.bind(this));
   },
 
   _updateDebugButtons: function() {
     this.consoleButton.disabled = !ConsolePanelView.enabled;
     this.jsShellButton.disabled = MetroUtils.immersive;
   },
-
-  _updateZoomButtons: function() {
-    let zoomDisabled = !InputSourceHelper.isPrecise;
-    this.zoomOutButton.disabled = this.zoomInButton.disabled = zoomDisabled;
-  }
   };
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -974,18 +974,16 @@ var BrowserUI = {
       case "cmd_close":
       case "cmd_newTab":
       case "cmd_closeTab":
       case "cmd_undoCloseTab":
       case "cmd_actions":
       case "cmd_panel":
       case "cmd_flyout_back":
       case "cmd_sanitize":
-      case "cmd_zoomin":
-      case "cmd_zoomout":
       case "cmd_volumeLeft":
       case "cmd_volumeRight":
       case "cmd_openFile":
       case "cmd_savePage":
         isSupported = true;
         break;
       default:
         isSupported = false;
@@ -1077,22 +1075,16 @@ var BrowserUI = {
         break;
       case "cmd_flyout_back":
         FlyoutPanelsUI.hide();
         MetroUtils.showSettingsFlyout();
         break;
       case "cmd_panel":
         PanelUI.toggle();
         break;
-      case "cmd_zoomin":
-        Browser.zoom(-1);
-        break;
-      case "cmd_zoomout":
-        Browser.zoom(1);
-        break;
       case "cmd_volumeLeft":
         // Zoom in (portrait) or out (landscape)
         Browser.zoom(Util.isPortrait() ? -1 : 1);
         break;
       case "cmd_volumeRight":
         // Zoom out (portrait) or in (landscape)
         Browser.zoom(Util.isPortrait() ? 1 : -1);
         break;
--- a/browser/metro/base/content/browser.xul
+++ b/browser/metro/base/content/browser.xul
@@ -90,18 +90,16 @@
     <command id="cmd_flyout_back" oncommand="CommandUpdater.doCommand(this.id);"/>
     <command id="cmd_addBookmark" oncommand="CommandUpdater.doCommand(this.id);"/>
     <command id="cmd_bookmarks" oncommand="CommandUpdater.doCommand(this.id);"/>
     <command id="cmd_history" oncommand="CommandUpdater.doCommand(this.id);"/>
     <command id="cmd_sanitize" oncommand="CommandUpdater.doCommand(this.id);"/>
     <command id="cmd_contextUI" oncommand="CommandUpdater.doCommand(this.id);"/>
 
     <!-- screen/display -->
-    <command id="cmd_zoomin" observes="bcast_contentShowing" oncommand="CommandUpdater.doCommand(this.id);"/>
-    <command id="cmd_zoomout" observes="bcast_contentShowing" oncommand="CommandUpdater.doCommand(this.id);"/>
     <command id="cmd_lockscreen" oncommand="CommandUpdater.doCommand(this.id);"/>
 
     <command id="cmd_volumeLeft" observes="bcast_contentShowing" oncommand="CommandUpdater.doCommand(this.id);"/>
     <command id="cmd_volumeRight" observes="bcast_contentShowing" oncommand="CommandUpdater.doCommand(this.id);"/>
 
     <!-- scrolling -->
     <command id="cmd_scrollPageUp" oncommand="CommandUpdater.doCommand(this.id);"/>
     <command id="cmd_scrollPageDown" oncommand="CommandUpdater.doCommand(this.id);"/>
@@ -138,18 +136,16 @@
     <key id="key_forceReload2" key="r" modifiers="accel,shift" command="cmd_forceReload"/>
     <key id="key_focusURL" key="l" modifiers="accel" command="cmd_openLocation"/>
     <key id="key_focusURL2" key="&urlbar.accesskey;" modifiers="alt" command="cmd_openLocation"/>
     <key id="key_home" keycode="VK_HOME" modifiers="accel" command="cmd_home"/>
     <key id="key_open" key="o" modifiers="accel" command="cmd_openFile"/>
     <key id="key_save" key="s" modifiers="accel" command="cmd_savePage"/>
 
     <!-- misc -->
-    <key id="key_zoomin" key="+" modifiers="accel" command="cmd_zoomin"/>
-    <key id="key_zoomout" key="-" modifiers="accel" command="cmd_zoomout"/>
     <key id="key_find" key="f" modifiers="accel" command="cmd_find"/>
     <key id="key_find" key="/" command="cmd_find"/>
     <key id="key_findNext" keycode="VK_F3" command="cmd_findNext"/>
     <key id="key_findNext2" key="g" modifiers="accel" command="cmd_findNext"/>
     <key id="key_findPrevious" keycode="VK_F3" modifiers="shift" command="cmd_findPrevious"/>
     <key id="key_findPrevious2" key="g" modifiers="accel,shift" command="cmd_findPrevious"/>
     <key id="key_quit" key="q" modifiers="accel" command="cmd_quit"/>
     <key id="key_addBoomkark" key="d" modifiers="accel" command="cmd_addBookmark"/>
@@ -347,18 +343,16 @@
         <toolbarbutton id="tool-reload" oncommand="CommandUpdater.doCommand(event.shiftKey ? 'cmd_forceReload' : 'cmd_reload');"/>
         <toolbarbutton id="tool-stop" command="cmd_stop"/>
 
         <!-- developer buttons -->
         <toolbarbutton id="console-button" oncommand="Appbar.onConsoleButton()"/>
         <toolbarbutton id="jsshell-button" oncommand="Appbar.onJSShellButton()"/>
 
         <toolbarbutton id="download-button" oncommand="Appbar.onDownloadButton()"/>
-        <toolbarbutton id="zoomout-button" oncommand="Appbar.onZoomOutButton()"/>
-        <toolbarbutton id="zoomin-button" oncommand="Appbar.onZoomInButton()"/>
         <toolbarbutton id="star-button" type="checkbox" oncommand="Appbar.onStarButton()"/>
         <toolbarbutton id="pin-button" type="checkbox" oncommand="Appbar.onPinButton()"/>
         <toolbarbutton id="more-button" onclick="Appbar.onMoreButton(event)"/>
       </toolbar>
     </appbar>
 
     <!-- Context button bar -->
     <appbar id="contextappbar">
--- a/browser/metro/theme/browser.css
+++ b/browser/metro/theme/browser.css
@@ -390,35 +390,16 @@ appbar > toolbar > toolbarbutton:active 
 #plugin-button:hover {
   -moz-image-region: rect(40px, 80px, 80px, 40px) !important;
 }
 #plugin-button:active {
   -moz-image-region: rect(80px, 80px, 120px, 40px) !important;
 }
 
 /* Page-Specific */
-#zoomout-button {
-  -moz-image-region: rect(0px, 120px, 40px, 80px) !important;
-}
-#zoomout-button:hover {
-  -moz-image-region: rect(40px, 120px, 80px, 80px) !important;
-}
-#zoomout-button:active {
-  -moz-image-region: rect(80px, 120px, 120px, 80px) !important;
-}
-
-#zoomin-button {
-  -moz-image-region: rect(0px, 160px, 40px, 120px) !important;
-}
-#zoomin-button:hover {
-  -moz-image-region: rect(40px, 160px, 80px, 120px) !important;
-}
-#zoomin-button:active {
-  -moz-image-region: rect(80px, 160px, 120px, 120px) !important;
-}
 
 #pin-button {
   -moz-image-region: rect(0px, 240px, 40px, 200px) !important;
 }
 #pin-button:hover {
   -moz-image-region: rect(40px, 240px, 80px, 200px) !important;
 }
 #pin-button:active {
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -2417,21 +2417,17 @@ nsScriptSecurityManager::nsScriptSecurit
 {
     MOZ_STATIC_ASSERT(sizeof(intptr_t) == sizeof(void*),
                       "intptr_t and void* have different lengths on this platform. "
                       "This may cause a security failure with the SecurityLevel union.");
 }
 
 nsresult nsScriptSecurityManager::Init()
 {
-    nsXPConnect* xpconnect = nsXPConnect::GetXPConnect();
-     if (!xpconnect)
-        return NS_ERROR_FAILURE;
-
-    NS_ADDREF(sXPConnect = xpconnect);
+    NS_ADDREF(sXPConnect = nsXPConnect::XPConnect());
 
     JSContext* cx = GetSafeJSContext();
     if (!cx) return NS_ERROR_FAILURE;   // this can happen of xpt loading fails
     
     ::JS_BeginRequest(cx);
     if (sEnabledID == JSID_VOID)
         sEnabledID = INTERNED_STRING_TO_JSID(cx, ::JS_InternString(cx, "enabled"));
     ::JS_EndRequest(cx);
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -356,20 +356,17 @@ nsContentUtils::Init()
     NS_WARNING("Init() called twice");
 
     return NS_OK;
   }
 
   nsresult rv = NS_GetNameSpaceManager(&sNameSpaceManager);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsXPConnect* xpconnect = nsXPConnect::GetXPConnect();
-  NS_ENSURE_TRUE(xpconnect, NS_ERROR_FAILURE);
-
-  sXPConnect = xpconnect;
+  sXPConnect = nsXPConnect::XPConnect();
 
   sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
   if(!sSecurityManager)
     return NS_ERROR_FAILURE;
   NS_ADDREF(sSecurityManager);
 
   rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
   if (NS_FAILED(rv)) {
--- a/content/html/content/src/HTMLImageElement.cpp
+++ b/content/html/content/src/HTMLImageElement.cpp
@@ -173,29 +173,39 @@ HTMLImageElement::GetXY()
   nsPoint origin(frame->GetOffsetTo(layer));
   // Convert to pixels using that scale
   point.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
   point.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
 
   return point;
 }
 
+int32_t
+HTMLImageElement::X()
+{
+  return GetXY().x;
+}
+
+int32_t
+HTMLImageElement::Y()
+{
+  return GetXY().y;
+}
+
 NS_IMETHODIMP
 HTMLImageElement::GetX(int32_t* aX)
 {
-  *aX = GetXY().x;
-
+  *aX = X();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLImageElement::GetY(int32_t* aY)
 {
-  *aY = GetXY().y;
-
+  *aY = Y();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLImageElement::GetHeight(uint32_t* aHeight)
 {
   *aHeight = Height();
 
--- a/content/html/content/src/HTMLImageElement.h
+++ b/content/html/content/src/HTMLImageElement.h
@@ -160,16 +160,24 @@ public:
   {
     SetHTMLAttr(nsGkAtoms::longdesc, aLongDesc, aError);
   }
   void SetBorder(const nsAString& aBorder, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::border, aBorder, aError);
   }
 
+  int32_t X();
+  int32_t Y();
+  // Uses XPCOM GetLowsrc.
+  void SetLowsrc(const nsAString& aLowsrc, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::lowsrc, aLowsrc, aError);
+  }
+
 protected:
   nsIntPoint GetXY();
   virtual void GetItemValueText(nsAString& text) MOZ_OVERRIDE;
   virtual void SetItemValueText(const nsAString& text) MOZ_OVERRIDE;
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 };
 
new file mode 100644
--- /dev/null
+++ b/content/media/test/crashtests/878014.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script>
+try { o2 = new window.AudioContext(1, 15, 44100); } catch(e) { }
+try { o5 = o2.createDelay(0.1); } catch(e) { }
+try { o6 = o2.createPanner(); } catch(e) { }
+try { o8 = o2.createBufferSource(); } catch(e) { }
+try { o9 = (function() {
+var buf = o2.createBuffer(1, 12134, o2.sampleRate);
+for(var j=0; j<1; ++j) {
+for(var i=0; i<12134; ++i) { buf.getChannelData(j)[i] = Math.sin(i * (-127));}
+}
+return buf;
+})(); } catch(e) { }
+try { o8.buffer = o9; } catch(e) { }
+try { o8.connect(o6); } catch(e) { }
+try { o6.connect(o5, 0, 0) } catch(e) { }
+try { o8.buffer = (function() {
+var buf = o2.createBuffer(1, 5409, o2.sampleRate);
+for(var j=0; j<1; ++j) {
+for(var i=0; i<5409; ++i) { buf.getChannelData(j)[i] = Math.sin(i * (-1));}
+}
+return buf;
+})(); } catch(e) { }
+setTimeout(function() { try { o5.delayTime.setValueAtTime(0.78, 121560862.56366833); } catch(e) { } setTimeout(done, 0); },128)
+try { o5.delayTime.value = 0.4283; } catch(e) { }
+
+function done() {
+  document.documentElement.removeAttribute("class");
+}
+</script>
new file mode 100644
--- /dev/null
+++ b/content/media/test/crashtests/878328.html
@@ -0,0 +1,5 @@
+<script>
+o1 = new window.AudioContext(2, 7, 44100);
+o5 = o1.createDelay(1);
+o5.delayTime.setValueCurveAtTime(new Float32Array(3), 1.7976931348623157e+308, 0.64);
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/media/test/crashtests/878407.html
@@ -0,0 +1,11 @@
+<script>
+o1 = new window.AudioContext();
+o4 = o1.createDelay(0.4468);
+o6 = o1.createPanner();
+o7 = (function() {var buf = o1.createBuffer(1, 1000, o1.sampleRate);for(var j=0; j<1; ++j) {for(var i=0; i<1000; ++i) {buf.getChannelData(j)[i] = Math.sin(i * (-15));}}return buf;})();
+o8 = o1.createBufferSource();
+o8.buffer = o7;
+o8.connect(o6);
+o6.connect(o4)
+o4.delayTime.setValueAtTime(0.6019893103749466289898, 0.26)
+</script>
new file mode 100644
--- /dev/null
+++ b/content/media/test/crashtests/878478.html
@@ -0,0 +1,30 @@
+<script>
+var Context0= new AudioContext()
+var BufferSource0=Context0.createBufferSource();
+
+BufferSource0.loop=true;
+
+BufferSource0.buffer=function(){
+	var channels=3; 
+	var length=97252;
+	var Buffer=Context0.createBuffer(channels,length,Context0.sampleRate);
+	for(var y=0;y<channels;y++){
+		var bufferData= Buffer.getChannelData(y);
+		for (var i = 0; i < length; ++i) { bufferData[i] = 1;}
+	};
+	return Buffer;
+}();
+
+BufferSource0.playbackRate.cancelScheduledValues(0.4);
+
+BufferSource0.loopEnd=5e-324;
+
+BufferSource0.buffer=function(){
+	var length=26590;
+	var Buffer=Context0.createBuffer(1,length,Context0.sampleRate);
+	var bufferData= Buffer.getChannelData(0);
+	for (var i = 0; i < length; ++i) { bufferData[i] = 1};
+	return Buffer;
+}();
+
+</script>
--- a/content/media/test/crashtests/crashtests.list
+++ b/content/media/test/crashtests/crashtests.list
@@ -27,8 +27,12 @@ load 876024-1.html
 load 876024-2.html
 load 876118.html
 load 876207.html
 load 876215.html
 load 876249.html
 load 876252.html
 load 876834.html
 load 877820.html
+load 878014.html
+load 878328.html
+load 878407.html
+load 878478.html
--- a/content/media/webaudio/AudioBufferSourceNode.cpp
+++ b/content/media/webaudio/AudioBufferSourceNode.cpp
@@ -673,16 +673,20 @@ AudioBufferSourceNode::SendLoopParameter
       actualLoopEnd = length;
     }
     int32_t loopStartTicks = NS_lround(actualLoopStart * rate);
     int32_t loopEndTicks = NS_lround(actualLoopEnd * rate);
     if (loopStartTicks < loopEndTicks) {
       SendInt32ParameterToStream(LOOPSTART, loopStartTicks);
       SendInt32ParameterToStream(LOOPEND, loopEndTicks);
       SendInt32ParameterToStream(LOOP, 1);
+    } else {
+      // Be explicit about looping not happening if the offsets make
+      // looping impossible.
+      SendInt32ParameterToStream(LOOP, 0);
     }
   } else if (!mLoop) {
     SendInt32ParameterToStream(LOOP, 0);
   }
 }
 
 }
 }
--- a/content/media/webaudio/AudioParam.h
+++ b/content/media/webaudio/AudioParam.h
@@ -48,16 +48,20 @@ public:
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   // We override SetValueCurveAtTime to convert the Float32Array to the wrapper
   // object.
   void SetValueCurveAtTime(const Float32Array& aValues, double aStartTime, double aDuration, ErrorResult& aRv)
   {
+    if (!WebAudioUtils::IsTimeValid(aStartTime)) {
+      aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+      return;
+    }
     AudioParamTimeline::SetValueCurveAtTime(aValues.Data(), aValues.Length(),
                                             aStartTime, aDuration, aRv);
     mCallback(mNode);
   }
 
   // We override the rest of the mutating AudioParamTimeline methods in order to make
   // sure that the callback is called every time that this object gets mutated.
   void SetValue(float aValue)
--- a/content/media/webaudio/DelayNode.cpp
+++ b/content/media/webaudio/DelayNode.cpp
@@ -111,17 +111,17 @@ public:
   {
     if (aNumberOfChannels == 0) {
       return false;
     }
     if (mBuffer.Length() == 0) {
       if (!mBuffer.SetLength(aNumberOfChannels)) {
         return false;
       }
-      const int32_t numFrames = NS_lround(mMaxDelay * aSampleRate);
+      const int32_t numFrames = ceil(mMaxDelay * aSampleRate);
       for (uint32_t channel = 0; channel < aNumberOfChannels; ++channel) {
         if (!mBuffer[channel].SetLength(numFrames)) {
           return false;
         }
         memset(mBuffer[channel].Elements(), 0, numFrames * sizeof(float));
       }
     } else if (mBuffer.Length() != aNumberOfChannels) {
       // TODO: Handle changes in the channel count
@@ -168,17 +168,17 @@ public:
     if (!EnsureBuffer(numChannels, aStream->SampleRate())) {
       aOutput->SetNull(0);
       return;
     }
 
     AllocateAudioBlock(numChannels, aOutput);
 
     double delayTime = 0;
-    float computedDelay[WEBAUDIO_BLOCK_SIZE];
+    double computedDelay[WEBAUDIO_BLOCK_SIZE];
     // Use a smoothing range of 20ms
     const double smoothingRate = WebAudioUtils::ComputeSmoothingRate(0.02, aStream->SampleRate());
 
     if (mDelay.HasSimpleValue()) {
       delayTime = std::max(0.0, std::min(mMaxDelay, double(mDelay.GetValue())));
       if (firstTime) {
         // Initialize this only the first time to make sure that mCurrentDelayTime
         // has a valid value when we try to change the delay time further below.
--- a/content/media/webaudio/test/Makefile.in
+++ b/content/media/webaudio/test/Makefile.in
@@ -30,16 +30,17 @@ MOCHITEST_FILES := \
   test_AudioContext.html \
   test_AudioListener.html \
   test_AudioParam.html \
   test_audioParamExponentialRamp.html \
   test_audioParamLinearRamp.html \
   test_audioParamSetCurveAtTime.html \
   test_audioParamSetCurveAtTimeZeroDuration.html \
   test_audioParamSetTargetAtTime.html \
+  test_audioParamSetValueAtTime.html \
   test_audioParamTimelineDestinationOffset.html \
   test_audioBufferSourceNode.html \
   test_audioBufferSourceNodeEnded.html \
   test_audioBufferSourceNodeGain.html \
   test_audioBufferSourceNodeGainInLoop.html \
   test_audioBufferSourceNodeLazyLoopParam.html \
   test_audioBufferSourceNodeLoop.html \
   test_audioBufferSourceNodeLoopStartEnd.html \
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/test_audioParamSetValueAtTime.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test AudioParam.linearRampToValue</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="webaudio.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+var V0 = 0.1;
+var V1 = 0.9;
+var T0 = 0;
+
+var gTest = {
+  length: 2048,
+  numberOfChannels: 1,
+  createGraph: function(context) {
+    var sourceBuffer = context.createBuffer(1, 2048, context.sampleRate);
+    for (var i = 0; i < 2048; ++i) {
+      sourceBuffer.getChannelData(0)[i] = 1;
+    }
+
+    var source = context.createBufferSource();
+    source.buffer = sourceBuffer;
+
+    var gain = context.createGain();
+    gain.gain.value = 0;
+    gain.gain.setValueAtTime(V0, 1024/context.sampleRate);
+
+    source.connect(gain);
+
+    source.start(0);
+    return gain;
+  },
+  createExpectedBuffers: function(context) {
+    var expectedBuffer = context.createBuffer(1, 2048, context.sampleRate);
+    for (var i = 1024; i < 2048; ++i) {
+      expectedBuffer.getChannelData(0)[i] = 0.1;
+    }
+    return expectedBuffer;
+  },
+};
+
+runTest();
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/xul/content/src/nsXULPopupListener.cpp
+++ b/content/xul/content/src/nsXULPopupListener.cpp
@@ -196,20 +196,19 @@ nsXULPopupListener::HandleEvent(nsIDOMEv
   }
   else {
     // Only open popups when the left mouse button is down.
     mouseEvent->GetButton(&button);
     if (button != 0)
       return NS_OK;
   }
 
-  // Open the popup and cancel the default handling of the event.
+  // Open the popup. LaunchPopup will call StopPropagation and PreventDefault
+  // in the right situations.
   LaunchPopup(aEvent, targetContent);
-  aEvent->StopPropagation();
-  aEvent->PreventDefault();
 
   return NS_OK;
 }
 
 #ifndef NS_CONTEXT_MENU_IS_MOUSEUP
 nsresult
 nsXULPopupListener::FireFocusOnTargetContent(nsIDOMNode* aTargetNode)
 {
@@ -323,31 +322,34 @@ GetImmediateChild(nsIContent* aContent, 
 // (popup, context) and uses that attribute's value as an ID for
 // the popup content in the document.
 //
 nsresult
 nsXULPopupListener::LaunchPopup(nsIDOMEvent* aEvent, nsIContent* aTargetContent)
 {
   nsresult rv = NS_OK;
 
+  nsAutoString identifier;
   nsIAtom* type = mIsContext ? nsGkAtoms::context : nsGkAtoms::popup;
-
-  nsAutoString identifier;
-  mElement->GetAttr(kNameSpaceID_None, type, identifier);
+  bool hasPopupAttr = mElement->GetAttr(kNameSpaceID_None, type, identifier);
 
   if (identifier.IsEmpty()) {
-    if (type == nsGkAtoms::popup) {
-      mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::menu, identifier);
-    } else {
-      mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::contextmenu, identifier);
-    }
-    if (identifier.IsEmpty())
-      return rv;
+    hasPopupAttr = mElement->GetAttr(kNameSpaceID_None,
+                          mIsContext ? nsGkAtoms::contextmenu : nsGkAtoms::menu,
+                          identifier) || hasPopupAttr;
   }
 
+  if (hasPopupAttr) {
+    aEvent->StopPropagation();
+    aEvent->PreventDefault();
+  }
+
+  if (identifier.IsEmpty())
+    return rv;
+
   // Try to find the popup content and the document.
   nsCOMPtr<nsIDocument> document = mElement->GetDocument();
   if (!document) {
     NS_WARNING("No document!");
     return NS_ERROR_FAILURE;
   }
 
   // Handle the _child case for popups and context menus
rename from dom/base/nsBarProps.cpp
rename to dom/base/BarProps.cpp
--- a/dom/base/nsBarProps.cpp
+++ b/dom/base/BarProps.cpp
@@ -1,328 +1,323 @@
 /* -*- 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 "nsBarProps.h"
-
-#include "nsCOMPtr.h"
-#include "nscore.h"
+#include "mozilla/dom/BarProps.h"
+#include "mozilla/dom/BarPropBinding.h"
+#include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
-#include "nsStyleConsts.h"
 #include "nsIDocShell.h"
-#include "nsIScriptSecurityManager.h"
 #include "nsIScrollable.h"
-#include "nsIWebBrowserChrome.h"
-#include "nsIDOMWindow.h"
-#include "nsDOMClassInfoID.h"
-#include "nsContentUtils.h"
+
+namespace mozilla {
+namespace dom {
 
 //
 //  Basic (virtual) BarProp class implementation
 //
-nsBarProp::nsBarProp(nsGlobalWindow *aWindow)
+BarProp::BarProp(nsGlobalWindow *aWindow)
+  : mDOMWindow(aWindow)
 {
-  mDOMWindow = aWindow;
-  nsISupports *supwin = static_cast<nsIScriptGlobalObject *>(aWindow);
-  mDOMWindowWeakref = do_GetWeakReference(supwin);
+  SetIsDOMBinding();
 }
 
-nsBarProp::~nsBarProp()
+BarProp::~BarProp()
 {
 }
 
-
-DOMCI_DATA(BarProp, nsBarProp)
+nsPIDOMWindow*
+BarProp::GetParentObject() const
+{
+  return mDOMWindow;
+}
 
-// QueryInterface implementation for BarProp
-NS_INTERFACE_MAP_BEGIN(nsBarProp)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMBarProp)
+JSObject*
+BarProp::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return BarPropBinding::Wrap(aCx, aScope, this);
+}
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(BarProp, mDOMWindow)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(BarProp)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(BarProp)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BarProp)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BarProp)
 NS_INTERFACE_MAP_END
 
-
-NS_IMPL_ADDREF(nsBarProp)
-NS_IMPL_RELEASE(nsBarProp)
-
-NS_IMETHODIMP
-nsBarProp::GetVisibleByFlag(bool *aVisible, uint32_t aChromeFlag)
+bool
+BarProp::GetVisibleByFlag(uint32_t aChromeFlag, ErrorResult& aRv)
 {
-  *aVisible = false;
-
   nsCOMPtr<nsIWebBrowserChrome> browserChrome = GetBrowserChrome();
-  NS_ENSURE_TRUE(browserChrome, NS_OK);
+  NS_ENSURE_TRUE(browserChrome, false);
 
   uint32_t chromeFlags;
 
-  NS_ENSURE_SUCCESS(browserChrome->GetChromeFlags(&chromeFlags),
-                    NS_ERROR_FAILURE);
-  if (chromeFlags & aChromeFlag)
-    *aVisible = true;
+  if (NS_FAILED(browserChrome->GetChromeFlags(&chromeFlags))) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return false;
+  }
 
-  return NS_OK;
+  return (chromeFlags & aChromeFlag);
 }
 
-NS_IMETHODIMP
-nsBarProp::SetVisibleByFlag(bool aVisible, uint32_t aChromeFlag)
+void
+BarProp::SetVisibleByFlag(bool aVisible, uint32_t aChromeFlag,
+                          ErrorResult& aRv)
 {
   nsCOMPtr<nsIWebBrowserChrome> browserChrome = GetBrowserChrome();
-  NS_ENSURE_TRUE(browserChrome, NS_OK);
+  NS_ENSURE_TRUE_VOID(browserChrome);
 
-  if (!nsContentUtils::IsCallerChrome())
-    return NS_OK;
+  if (!nsContentUtils::IsCallerChrome()) {
+    return;
+  }
 
   uint32_t chromeFlags;
 
-  NS_ENSURE_SUCCESS(browserChrome->GetChromeFlags(&chromeFlags),
-                    NS_ERROR_FAILURE);
+  if (NS_FAILED(browserChrome->GetChromeFlags(&chromeFlags))) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
   if (aVisible)
     chromeFlags |= aChromeFlag;
   else
     chromeFlags &= ~aChromeFlag;
-  NS_ENSURE_SUCCESS(browserChrome->SetChromeFlags(chromeFlags),
-                    NS_ERROR_FAILURE);
 
-  return NS_OK;
+  if (NS_FAILED(browserChrome->SetChromeFlags(chromeFlags))) {
+    aRv.Throw(NS_ERROR_FAILURE);
+  }
 }
 
 already_AddRefed<nsIWebBrowserChrome>
-nsBarProp::GetBrowserChrome()
+BarProp::GetBrowserChrome()
 {
-  // Check that the window is still alive.
-  nsCOMPtr<nsIDOMWindow> domwin(do_QueryReferent(mDOMWindowWeakref));
-  if (!domwin)
+  if (!mDOMWindow) {
     return nullptr;
+  }
 
   return mDOMWindow->GetWebBrowserChrome();
 }
 
 //
 // MenubarProp class implementation
 //
 
-nsMenubarProp::nsMenubarProp(nsGlobalWindow *aWindow) 
-  : nsBarProp(aWindow)
+MenubarProp::MenubarProp(nsGlobalWindow *aWindow)
+  : BarProp(aWindow)
 {
 }
 
-nsMenubarProp::~nsMenubarProp()
+MenubarProp::~MenubarProp()
 {
 }
 
-NS_IMETHODIMP
-nsMenubarProp::GetVisible(bool *aVisible)
+bool
+MenubarProp::GetVisible(ErrorResult& aRv)
 {
-  return nsBarProp::GetVisibleByFlag(aVisible,
-                                     nsIWebBrowserChrome::CHROME_MENUBAR);
+  return BarProp::GetVisibleByFlag(nsIWebBrowserChrome::CHROME_MENUBAR, aRv);
 }
 
-NS_IMETHODIMP
-nsMenubarProp::SetVisible(bool aVisible)
+void
+MenubarProp::SetVisible(bool aVisible, ErrorResult& aRv)
 {
-  return nsBarProp::SetVisibleByFlag(aVisible,
-                                     nsIWebBrowserChrome::CHROME_MENUBAR);
+  BarProp::SetVisibleByFlag(aVisible, nsIWebBrowserChrome::CHROME_MENUBAR, aRv);
 }
 
 //
 // ToolbarProp class implementation
 //
 
-nsToolbarProp::nsToolbarProp(nsGlobalWindow *aWindow)
-  : nsBarProp(aWindow)
+ToolbarProp::ToolbarProp(nsGlobalWindow *aWindow)
+  : BarProp(aWindow)
 {
 }
 
-nsToolbarProp::~nsToolbarProp()
+ToolbarProp::~ToolbarProp()
 {
 }
 
-NS_IMETHODIMP
-nsToolbarProp::GetVisible(bool *aVisible)
+bool
+ToolbarProp::GetVisible(ErrorResult& aRv)
 {
-  return nsBarProp::GetVisibleByFlag(aVisible,
-                                     nsIWebBrowserChrome::CHROME_TOOLBAR);
+  return BarProp::GetVisibleByFlag(nsIWebBrowserChrome::CHROME_TOOLBAR, aRv);
 }
 
-NS_IMETHODIMP
-nsToolbarProp::SetVisible(bool aVisible)
+void
+ToolbarProp::SetVisible(bool aVisible, ErrorResult& aRv)
 {
-  return nsBarProp::SetVisibleByFlag(aVisible,
-                                     nsIWebBrowserChrome::CHROME_TOOLBAR);
+  BarProp::SetVisibleByFlag(aVisible, nsIWebBrowserChrome::CHROME_TOOLBAR,
+                            aRv);
 }
 
 //
 // LocationbarProp class implementation
 //
 
-nsLocationbarProp::nsLocationbarProp(nsGlobalWindow *aWindow)
-  : nsBarProp(aWindow)
+LocationbarProp::LocationbarProp(nsGlobalWindow *aWindow)
+  : BarProp(aWindow)
 {
 }
 
-nsLocationbarProp::~nsLocationbarProp()
+LocationbarProp::~LocationbarProp()
 {
 }
 
-NS_IMETHODIMP
-nsLocationbarProp::GetVisible(bool *aVisible)
+bool
+LocationbarProp::GetVisible(ErrorResult& aRv)
 {
-  return
-    nsBarProp::GetVisibleByFlag(aVisible,
-                                nsIWebBrowserChrome::CHROME_LOCATIONBAR);
+  return BarProp::GetVisibleByFlag(nsIWebBrowserChrome::CHROME_LOCATIONBAR,
+                                   aRv);
 }
 
-NS_IMETHODIMP
-nsLocationbarProp::SetVisible(bool aVisible)
+void
+LocationbarProp::SetVisible(bool aVisible, ErrorResult& aRv)
 {
-  return
-    nsBarProp::SetVisibleByFlag(aVisible,
-                                nsIWebBrowserChrome::CHROME_LOCATIONBAR);
+  BarProp::SetVisibleByFlag(aVisible, nsIWebBrowserChrome::CHROME_LOCATIONBAR,
+                            aRv);
 }
 
 //
 // PersonalbarProp class implementation
 //
 
-nsPersonalbarProp::nsPersonalbarProp(nsGlobalWindow *aWindow)
-  : nsBarProp(aWindow)
+PersonalbarProp::PersonalbarProp(nsGlobalWindow *aWindow)
+  : BarProp(aWindow)
 {
 }
 
-nsPersonalbarProp::~nsPersonalbarProp()
+PersonalbarProp::~PersonalbarProp()
 {
 }
 
-NS_IMETHODIMP
-nsPersonalbarProp::GetVisible(bool *aVisible)
+bool
+PersonalbarProp::GetVisible(ErrorResult& aRv)
 {
-  return
-    nsBarProp::GetVisibleByFlag(aVisible,
-                                nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR);
+  return BarProp::GetVisibleByFlag(nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR,
+                                   aRv);
 }
 
-NS_IMETHODIMP
-nsPersonalbarProp::SetVisible(bool aVisible)
+void
+PersonalbarProp::SetVisible(bool aVisible, ErrorResult& aRv)
 {
-  return
-    nsBarProp::SetVisibleByFlag(aVisible,
-                                nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR);
+  BarProp::SetVisibleByFlag(aVisible,
+                            nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR,
+                            aRv);
 }
 
 //
 // StatusbarProp class implementation
 //
 
-nsStatusbarProp::nsStatusbarProp(nsGlobalWindow *aWindow)
-  : nsBarProp(aWindow)
+StatusbarProp::StatusbarProp(nsGlobalWindow *aWindow)
+  : BarProp(aWindow)
 {
 }
 
-nsStatusbarProp::~nsStatusbarProp()
+StatusbarProp::~StatusbarProp()
 {
 }
 
-NS_IMETHODIMP
-nsStatusbarProp::GetVisible(bool *aVisible)
+bool
+StatusbarProp::GetVisible(ErrorResult& aRv)
 {
-  return nsBarProp::GetVisibleByFlag(aVisible,
-                                     nsIWebBrowserChrome::CHROME_STATUSBAR);
+  return BarProp::GetVisibleByFlag(nsIWebBrowserChrome::CHROME_STATUSBAR, aRv);
 }
 
-NS_IMETHODIMP
-nsStatusbarProp::SetVisible(bool aVisible)
+void
+StatusbarProp::SetVisible(bool aVisible, ErrorResult& aRv)
 {
-  return nsBarProp::SetVisibleByFlag(aVisible,
-                                     nsIWebBrowserChrome::CHROME_STATUSBAR);
+  return BarProp::SetVisibleByFlag(aVisible,
+                                   nsIWebBrowserChrome::CHROME_STATUSBAR, aRv);
 }
 
 //
 // ScrollbarsProp class implementation
 //
 
-nsScrollbarsProp::nsScrollbarsProp(nsGlobalWindow *aWindow)
-: nsBarProp(aWindow)
+ScrollbarsProp::ScrollbarsProp(nsGlobalWindow *aWindow)
+: BarProp(aWindow)
 {
 }
 
-nsScrollbarsProp::~nsScrollbarsProp()
+ScrollbarsProp::~ScrollbarsProp()
 {
 }
 
-NS_IMETHODIMP
-nsScrollbarsProp::GetVisible(bool *aVisible)
+bool
+ScrollbarsProp::GetVisible(ErrorResult& aRv)
 {
-  *aVisible = true; // one assumes
-
-  nsCOMPtr<nsIDOMWindow> domwin(do_QueryReferent(mDOMWindowWeakref));
-  if (domwin) { // dom window not deleted
-    nsCOMPtr<nsIScrollable> scroller =
-      do_QueryInterface(mDOMWindow->GetDocShell());
+  if (!mDOMWindow) {
+    return true;
+  }
 
-    if (scroller) {
-      int32_t prefValue;
-      scroller->GetDefaultScrollbarPreferences(
-                  nsIScrollable::ScrollOrientation_Y, &prefValue);
-      if (prefValue == nsIScrollable::Scrollbar_Never) // try the other way
-        scroller->GetDefaultScrollbarPreferences(
-                    nsIScrollable::ScrollOrientation_X, &prefValue);
+  nsCOMPtr<nsIScrollable> scroller =
+    do_QueryInterface(mDOMWindow->GetDocShell());
 
-      if (prefValue == nsIScrollable::Scrollbar_Never)
-        *aVisible = false;
-    }
+  if (!scroller) {
+    return true;
   }
 
-  return NS_OK;
+  int32_t prefValue;
+  scroller->GetDefaultScrollbarPreferences(
+              nsIScrollable::ScrollOrientation_Y, &prefValue);
+  if (prefValue != nsIScrollable::Scrollbar_Never) {
+    return true;
+  }
+
+  scroller->GetDefaultScrollbarPreferences(
+              nsIScrollable::ScrollOrientation_X, &prefValue);
+  return prefValue != nsIScrollable::Scrollbar_Never;
 }
 
-NS_IMETHODIMP
-nsScrollbarsProp::SetVisible(bool aVisible)
+void
+ScrollbarsProp::SetVisible(bool aVisible, ErrorResult& aRv)
 {
-  if (!nsContentUtils::IsCallerChrome())
-    return NS_OK;
+  if (!nsContentUtils::IsCallerChrome()) {
+    return;
+  }
 
   /* Scrollbars, unlike the other barprops, implement visibility directly
      rather than handing off to the superclass (and from there to the
      chrome window) because scrollbar visibility uniquely applies only
      to the window making the change (arguably. it does now, anyway.)
      and because embedding apps have no interface for implementing this
      themselves, and therefore the implementation must be internal. */
 
-  nsCOMPtr<nsIDOMWindow> domwin(do_QueryReferent(mDOMWindowWeakref));
-  if (domwin) { // dom window must still exist. use away.
-    nsCOMPtr<nsIScrollable> scroller =
-      do_QueryInterface(mDOMWindow->GetDocShell());
+  nsCOMPtr<nsIScrollable> scroller =
+    do_QueryInterface(mDOMWindow->GetDocShell());
 
-    if (scroller) {
-      int32_t prefValue;
+  if (scroller) {
+    int32_t prefValue;
 
-      if (aVisible) {
-        prefValue = nsIScrollable::Scrollbar_Auto;
-      } else {
-        prefValue = nsIScrollable::Scrollbar_Never;
-      }
+    if (aVisible) {
+      prefValue = nsIScrollable::Scrollbar_Auto;
+    } else {
+      prefValue = nsIScrollable::Scrollbar_Never;
+    }
 
-      scroller->SetDefaultScrollbarPreferences(
-                  nsIScrollable::ScrollOrientation_Y, prefValue);
-      scroller->SetDefaultScrollbarPreferences(
-                  nsIScrollable::ScrollOrientation_X, prefValue);
-    }
+    scroller->SetDefaultScrollbarPreferences(
+                nsIScrollable::ScrollOrientation_Y, prefValue);
+    scroller->SetDefaultScrollbarPreferences(
+                nsIScrollable::ScrollOrientation_X, prefValue);
   }
 
   /* Notably absent is the part where we notify the chrome window using
      GetBrowserChrome()->SetChromeFlags(). Given the possibility of multiple
      DOM windows (multiple top-level windows, even) within a single
      chrome window, the historical concept of a single "has scrollbars"
      flag in the chrome is inapplicable, and we can't tell at this level
      whether we represent the particular DOM window that makes this decision
      for the chrome.
 
      So only this object (and its corresponding DOM window) knows whether
      scrollbars are visible. The corresponding chrome window will need to
      ask (one of) its DOM window(s) when it needs to know about scrollbar
      visibility, rather than caching its own copy of that information.
   */
-
-  return NS_OK;
 }
 
+} // namespace dom
+} // namespace mozilla
+
rename from dom/base/nsBarProps.h
rename to dom/base/BarProps.h
--- a/dom/base/nsBarProps.h
+++ b/dom/base/BarProps.h
@@ -4,108 +4,124 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* BarProps are the collection of little properties of DOM windows whose
    only property of their own is "visible".  They describe the window
    chrome which can be made visible or not through JavaScript by setting
    the appropriate property (window.menubar.visible)
 */
 
-#ifndef nsBarProps_h___
-#define nsBarProps_h___
+#ifndef mozilla_dom_BarProps_h
+#define mozilla_dom_BarProps_h
 
-#include "nscore.h"
-#include "nsIScriptContext.h"
-#include "nsIDOMBarProp.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/ErrorResult.h"
+#include "nsCycleCollectionParticipant.h"
 #include "nsIWeakReference.h"
+#include "nsWrapperCache.h"
+#include "nsAutoPtr.h"
 
 class nsGlobalWindow;
 class nsIWebBrowserChrome;
+class nsPIDOMWindow;
+
+namespace mozilla {
+namespace dom {
 
 // Script "BarProp" object
-class nsBarProp : public nsIDOMBarProp
+class BarProp : public nsISupports,
+                public nsWrapperCache
 {
 public:
-  explicit nsBarProp(nsGlobalWindow *aWindow);
-  virtual ~nsBarProp();
+  explicit BarProp(nsGlobalWindow *aWindow);
+  virtual ~BarProp();
+
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BarProp)
 
-  NS_DECL_ISUPPORTS
+  nsPIDOMWindow* GetParentObject() const;
 
-  NS_IMETHOD GetVisibleByFlag(bool *aVisible, uint32_t aChromeFlag);
-  NS_IMETHOD SetVisibleByFlag(bool aVisible, uint32_t aChromeFlag);
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  virtual bool GetVisible(ErrorResult& aRv) = 0;
+  virtual void SetVisible(bool aVisible, ErrorResult& aRv) = 0;
 
 protected:
+  bool GetVisibleByFlag(uint32_t aChromeFlag, ErrorResult& aRv);
+  void SetVisibleByFlag(bool aVisible, uint32_t aChromeFlag, ErrorResult &aRv);
+
   already_AddRefed<nsIWebBrowserChrome> GetBrowserChrome();
 
-  nsGlobalWindow             *mDOMWindow;
-  nsCOMPtr<nsIWeakReference>  mDOMWindowWeakref;
-  /* Note the odd double reference to the owning global window.
-     Since the corresponding DOM window nominally owns this object,
-     but refcounted ownership of this object can be handed off to
-     owners unknown, we need a weak ref back to the DOM window.
-     However we also need access to properties of the DOM Window
-     that aren't available through interfaces. Then it's either
-     a weak ref and some skanky casting, or this funky double ref.
-     Funky beats skanky, so here we are. */
+  nsRefPtr<nsGlobalWindow> mDOMWindow;
 };
 
 // Script "menubar" object
-class nsMenubarProp : public nsBarProp
+class MenubarProp MOZ_FINAL : public BarProp
 {
 public:
-  explicit nsMenubarProp(nsGlobalWindow *aWindow);
-  virtual ~nsMenubarProp();
+  explicit MenubarProp(nsGlobalWindow *aWindow);
+  virtual ~MenubarProp();
 
-  NS_DECL_NSIDOMBARPROP
+  virtual bool GetVisible(ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual void SetVisible(bool aVisible, ErrorResult& aRv) MOZ_OVERRIDE;
 };
 
 // Script "toolbar" object
-class nsToolbarProp : public nsBarProp
+class ToolbarProp MOZ_FINAL : public BarProp
 {
 public:
-  explicit nsToolbarProp(nsGlobalWindow *aWindow);
-  virtual ~nsToolbarProp();
+  explicit ToolbarProp(nsGlobalWindow *aWindow);
+  virtual ~ToolbarProp();
 
-  NS_DECL_NSIDOMBARPROP
+  virtual bool GetVisible(ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual void SetVisible(bool aVisible, ErrorResult& aRv) MOZ_OVERRIDE;
 };
 
 // Script "locationbar" object
-class nsLocationbarProp : public nsBarProp
+class LocationbarProp MOZ_FINAL : public BarProp
 {
 public:
-  explicit nsLocationbarProp(nsGlobalWindow *aWindow);
-  virtual ~nsLocationbarProp();
+  explicit LocationbarProp(nsGlobalWindow *aWindow);
+  virtual ~LocationbarProp();
 
-  NS_DECL_NSIDOMBARPROP
+  virtual bool GetVisible(ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual void SetVisible(bool aVisible, ErrorResult& aRv) MOZ_OVERRIDE;
 };
 
 // Script "personalbar" object
-class nsPersonalbarProp : public nsBarProp
+class PersonalbarProp MOZ_FINAL : public BarProp
 {
 public:
-  explicit nsPersonalbarProp(nsGlobalWindow *aWindow);
-  virtual ~nsPersonalbarProp();
+  explicit PersonalbarProp(nsGlobalWindow *aWindow);
+  virtual ~PersonalbarProp();
 
-  NS_DECL_NSIDOMBARPROP
+  virtual bool GetVisible(ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual void SetVisible(bool aVisible, ErrorResult& aRv) MOZ_OVERRIDE;
 };
 
 // Script "statusbar" object
-class nsStatusbarProp : public nsBarProp
+class StatusbarProp MOZ_FINAL : public BarProp
 {
 public:
-  explicit nsStatusbarProp(nsGlobalWindow *aWindow);
-  virtual ~nsStatusbarProp();
+  explicit StatusbarProp(nsGlobalWindow *aWindow);
+  virtual ~StatusbarProp();
 
-  NS_DECL_NSIDOMBARPROP
+  virtual bool GetVisible(ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual void SetVisible(bool aVisible, ErrorResult& aRv) MOZ_OVERRIDE;
 };
 
 // Script "scrollbars" object
-class nsScrollbarsProp : public nsBarProp
+class ScrollbarsProp MOZ_FINAL : public BarProp
 {
 public:
-  explicit nsScrollbarsProp(nsGlobalWindow *aWindow);
-  virtual ~nsScrollbarsProp();
+  explicit ScrollbarsProp(nsGlobalWindow *aWindow);
+  virtual ~ScrollbarsProp();
 
-  NS_DECL_NSIDOMBARPROP
+  virtual bool GetVisible(ErrorResult& aRv) MOZ_OVERRIDE;
+  virtual void SetVisible(bool aVisible, ErrorResult& aRv) MOZ_OVERRIDE;
 };
 
-#endif /* nsBarProps_h___ */
+} // namespace dom
+} // namespace mozilla
 
+#endif /* mozilla_dom_BarProps_h */
+
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -49,32 +49,33 @@ EXPORTS += [
     'nsPIWindowRoot.h',
     'nsStructuredCloneContainer.h',
     'nsWindowMemoryReporter.h',
     'nsWrapperCache.h',
     'nsWrapperCacheInlines.h',
 ]
 
 EXPORTS.mozilla.dom += [
+    'BarProps.h',
     'DOMCursor.h',
     'DOMError.h',
     'DOMRequest.h',
     'ScreenOrientation.h',
     'StructuredCloneTags.h',
     'URL.h',
 ]
 
 CPP_SOURCES += [
+    'BarProps.cpp',
     'Crypto.cpp',
     'DOMCursor.cpp',
     'DOMError.cpp',
     'DOMRequest.cpp',
     'Navigator.cpp',
     'URL.cpp',
-    'nsBarProps.cpp',
     'nsContentPermissionHelper.cpp',
     'nsDOMClassInfo.cpp',
     'nsDOMException.cpp',
     'nsDOMNavigationTiming.cpp',
     'nsDOMScriptObjectFactory.cpp',
     'nsDOMWindowList.cpp',
     'nsDOMWindowUtils.cpp',
     'nsFocusManager.cpp',
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -141,17 +141,16 @@
 #include "nsXMLHttpRequest.h"
 #include "nsIDOMSettingsManager.h"
 #include "nsIDOMContactManager.h"
 #include "nsIDOMPermissionSettings.h"
 #include "nsIDOMApplicationRegistry.h"
 
 // includes needed for the prototype chain interfaces
 #include "nsIDOMNavigator.h"
-#include "nsIDOMBarProp.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsIDOMElementCSSInlineStyle.h"
 #include "nsIDOMLinkStyle.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMCSSCharsetRule.h"
 #include "nsIDOMCSSImportRule.h"
 #include "nsIDOMCSSMediaRule.h"
 #include "nsIDOMCSSFontFaceRule.h"
@@ -480,18 +479,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(Plugin, nsPluginSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(PluginArray, nsPluginArraySH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MimeType, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MimeTypeArray, nsMimeTypeArraySH,
                            ARRAY_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(BarProp, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(History, nsHistorySH,
                            ARRAY_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_PRECREATE)
   NS_DEFINE_CLASSINFO_DATA(DOMPrototype, nsDOMConstructorSH,
                            DOM_BASE_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_PRECREATE |
                            nsIXPCScriptable::WANT_NEWRESOLVE |
                            nsIXPCScriptable::WANT_HASINSTANCE |
@@ -1517,20 +1514,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(MimeType, nsIDOMMimeType)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMimeType)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MimeTypeArray, nsIDOMMimeTypeArray)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMimeTypeArray)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(BarProp, nsIDOMBarProp)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMBarProp)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(History, nsIDOMHistory)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHistory)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -5,17 +5,16 @@
 
 DOMCI_CLASS(Window)
 DOMCI_CLASS(Location)
 DOMCI_CLASS(Navigator)
 DOMCI_CLASS(Plugin)
 DOMCI_CLASS(PluginArray)
 DOMCI_CLASS(MimeType)
 DOMCI_CLASS(MimeTypeArray)
-DOMCI_CLASS(BarProp)
 DOMCI_CLASS(History)
 DOMCI_CLASS(DOMPrototype)
 DOMCI_CLASS(DOMConstructor)
 
 // Core classes
 DOMCI_CLASS(DOMException)
 DOMCI_CLASS(Element)
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -12,17 +12,16 @@
 
 // Local Includes
 #include "nsGlobalWindow.h"
 #include "Navigator.h"
 #include "nsScreen.h"
 #include "nsHistory.h"
 #include "nsPerformance.h"
 #include "nsDOMNavigationTiming.h"
-#include "nsBarProps.h"
 #include "nsIDOMStorage.h"
 #include "nsIDOMStorageManager.h"
 #include "DOMStorage.h"
 #include "nsDOMOfflineResourceList.h"
 #include "nsError.h"
 #include "nsIIdleService.h"
 #include "nsIPowerManagerService.h"
 #include "nsISizeOfEventTarget.h"
@@ -56,16 +55,17 @@
 #include "nsMimeTypeArray.h"
 #include "nsNetUtil.h"
 #include "nsICachingChannel.h"
 #include "nsPluginArray.h"
 #include "nsIPluginHost.h"
 #include "nsPluginHost.h"
 #include "nsIPluginInstanceOwner.h"
 #include "nsGeolocation.h"
+#include "mozilla/dom/BarProps.h"
 #include "mozilla/dom/DesktopNotification.h"
 #include "nsContentCID.h"
 #include "nsLayoutStatics.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsAutoJSValHolder.h"
 #include "nsDOMMediaQueryList.h"
 #include "mozilla/dom/workers/Workers.h"
 #include "nsJSPrincipals.h"
@@ -1673,16 +1673,23 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
 #endif
 
   // Traverse stuff from nsPIDOMWindow
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedNode)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioContexts)
+
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMenubar)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mToolbar)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocationbar)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPersonalbar)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
   nsGlobalWindow::CleanupCachedXBLHandlers(tmp);
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
@@ -1719,16 +1726,23 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
 #endif
 
   // Unlink stuff from nsPIDOMWindow
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioContexts)
+
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMenubar)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mToolbar)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocationbar)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPersonalbar)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 struct TraceData
 {
   const TraceCallbacks& callbacks;
   void* closure;
 };
 
@@ -3581,126 +3595,126 @@ nsGlobalWindow::GetPrompter(nsIPrompt** 
   nsCOMPtr<nsIPrompt> prompter(do_GetInterface(mDocShell));
   NS_ENSURE_TRUE(prompter, NS_ERROR_NO_INTERFACE);
 
   NS_ADDREF(*aPrompt = prompter);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGlobalWindow::GetMenubar(nsIDOMBarProp** aMenubar)
+nsGlobalWindow::GetMenubar(nsISupports** aMenubar)
 {
   FORWARD_TO_OUTER(GetMenubar, (aMenubar), NS_ERROR_NOT_INITIALIZED);
 
   *aMenubar = nullptr;
 
   if (!mMenubar) {
-    mMenubar = new nsMenubarProp(this);
+    mMenubar = new MenubarProp(this);
     if (!mMenubar) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   NS_ADDREF(*aMenubar = mMenubar);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGlobalWindow::GetToolbar(nsIDOMBarProp** aToolbar)
+nsGlobalWindow::GetToolbar(nsISupports** aToolbar)
 {
   FORWARD_TO_OUTER(GetToolbar, (aToolbar), NS_ERROR_NOT_INITIALIZED);
 
   *aToolbar = nullptr;
 
   if (!mToolbar) {
-    mToolbar = new nsToolbarProp(this);
+    mToolbar = new ToolbarProp(this);
     if (!mToolbar) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   NS_ADDREF(*aToolbar = mToolbar);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGlobalWindow::GetLocationbar(nsIDOMBarProp** aLocationbar)
+nsGlobalWindow::GetLocationbar(nsISupports** aLocationbar)
 {
   FORWARD_TO_OUTER(GetLocationbar, (aLocationbar), NS_ERROR_NOT_INITIALIZED);
 
   *aLocationbar = nullptr;
 
   if (!mLocationbar) {
-    mLocationbar = new nsLocationbarProp(this);
+    mLocationbar = new LocationbarProp(this);
     if (!mLocationbar) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   NS_ADDREF(*aLocationbar = mLocationbar);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGlobalWindow::GetPersonalbar(nsIDOMBarProp** aPersonalbar)
+nsGlobalWindow::GetPersonalbar(nsISupports** aPersonalbar)
 {
   FORWARD_TO_OUTER(GetPersonalbar, (aPersonalbar), NS_ERROR_NOT_INITIALIZED);
 
   *aPersonalbar = nullptr;
 
   if (!mPersonalbar) {
-    mPersonalbar = new nsPersonalbarProp(this);
+    mPersonalbar = new PersonalbarProp(this);
     if (!mPersonalbar) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   NS_ADDREF(*aPersonalbar = mPersonalbar);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGlobalWindow::GetStatusbar(nsIDOMBarProp** aStatusbar)
+nsGlobalWindow::GetStatusbar(nsISupports** aStatusbar)
 {
   FORWARD_TO_OUTER(GetStatusbar, (aStatusbar), NS_ERROR_NOT_INITIALIZED);
 
   *aStatusbar = nullptr;
 
   if (!mStatusbar) {
-    mStatusbar = new nsStatusbarProp(this);
+    mStatusbar = new StatusbarProp(this);
     if (!mStatusbar) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   NS_ADDREF(*aStatusbar = mStatusbar);
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsGlobalWindow::GetScrollbars(nsIDOMBarProp** aScrollbars)
+mozilla::dom::BarProp*
+nsGlobalWindow::Scrollbars()
+{
+  if (!mScrollbars) {
+    mScrollbars = new ScrollbarsProp(this);
+  }
+
+  return mScrollbars;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetScrollbars(nsISupports** aScrollbars)
 {
   FORWARD_TO_OUTER(GetScrollbars, (aScrollbars), NS_ERROR_NOT_INITIALIZED);
 
-  *aScrollbars = nullptr;
-
-  if (!mScrollbars) {
-    mScrollbars = new nsScrollbarsProp(this);
-    if (!mScrollbars) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  NS_ADDREF(*aScrollbars = mScrollbars);
-
+  NS_ADDREF(*aScrollbars = Scrollbars());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetClosed(bool* aClosed)
 {
   FORWARD_TO_OUTER(GetClosed, (aClosed), NS_ERROR_NOT_INITIALIZED);
 
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -89,25 +89,23 @@
 
 // Idle fuzz time upper limit
 #define MAX_IDLE_FUZZ_TIME_MS 90000
 
 // Min idle notification time in seconds.
 #define MIN_IDLE_NOTIFICATION_TIME_S 1
 
 class nsIContent;
-class nsIDOMBarProp;
 class nsIDocument;
 class nsPresContext;
 class nsIDOMCrypto;
 class nsIDOMEvent;
 class nsIScrollableFrame;
 class nsIControllers;
 
-class nsBarProp;
 class nsLocation;
 class nsScreen;
 class nsHistory;
 class nsIDocShellLoadInfo;
 class WindowStateHolder;
 class nsGlobalWindowObserver;
 class nsGlobalWindow;
 class PostMessageEvent;
@@ -116,16 +114,17 @@ class nsDOMEventTargetHelper;
 class nsDOMOfflineResourceList;
 class nsDOMWindowUtils;
 class nsIIdleService;
 
 class nsWindowSizes;
 
 namespace mozilla {
 namespace dom {
+class BarProp;
 class Navigator;
 class URL;
 class SpeechSynthesis;
 namespace indexedDB {
 class IDBFactory;
 } // namespace indexedDB
 } // namespace dom
 } // namespace mozilla
@@ -763,16 +762,18 @@ public:
 #undef BEFOREUNLOAD_EVENT
 #undef ERROR_EVENT
 #undef EVENT
 
 #ifdef MOZ_WEBSPEECH
   mozilla::dom::SpeechSynthesis* GetSpeechSynthesisInternal();
 #endif
 
+  mozilla::dom::BarProp* Scrollbars();
+
 protected:
   // Array of idle observers that are notified of idle events.
   nsTObserverArray<IdleObserverHolder> mIdleObservers;
 
   // Idle timer used for function callbacks to notify idle observers.
   nsCOMPtr<nsITimer> mIdleTimer;
 
   // Idle fuzz time added to idle timer callbacks.
@@ -792,17 +793,17 @@ protected:
 
   nsCOMPtr <nsIIdleService> mIdleService;
 
   nsCOMPtr <nsIDOMMozWakeLock> mWakeLock;
 
   static bool sIdleObserversAPIFuzzTimeDisabled;
 
   friend class HashchangeCallback;
-  friend class nsBarProp;
+  friend class mozilla::dom::BarProp;
 
   // Object Management
   virtual ~nsGlobalWindow();
   void CleanUp(bool aIgnoreModalDialog);
   void ClearControllers();
   nsresult FinalClose();
 
   inline void MaybeClearInnerWindow(nsGlobalWindow* aExpectedInner)
@@ -1172,22 +1173,22 @@ protected:
   nsCOMPtr<nsIArray>            mArguments;
 
   // For |window.dialogArguments|, via |showModalDialog|.
   nsRefPtr<DialogValueHolder> mDialogArguments;
 
   nsRefPtr<Navigator>           mNavigator;
   nsRefPtr<nsScreen>            mScreen;
   nsRefPtr<nsDOMWindowList>     mFrames;
-  nsRefPtr<nsBarProp>           mMenubar;
-  nsRefPtr<nsBarProp>           mToolbar;
-  nsRefPtr<nsBarProp>           mLocationbar;
-  nsRefPtr<nsBarProp>           mPersonalbar;
-  nsRefPtr<nsBarProp>           mStatusbar;
-  nsRefPtr<nsBarProp>           mScrollbars;
+  nsRefPtr<mozilla::dom::BarProp> mMenubar;
+  nsRefPtr<mozilla::dom::BarProp> mToolbar;
+  nsRefPtr<mozilla::dom::BarProp> mLocationbar;
+  nsRefPtr<mozilla::dom::BarProp> mPersonalbar;
+  nsRefPtr<mozilla::dom::BarProp> mStatusbar;
+  nsRefPtr<mozilla::dom::BarProp> mScrollbars;
   nsRefPtr<nsDOMWindowUtils>    mWindowUtils;
   nsString                      mStatus;
   nsString                      mDefaultStatus;
   nsGlobalWindowObserver*       mObserver;
   nsCOMPtr<nsIDOMCrypto>        mCrypto;
 
   nsCOMPtr<nsIDOMStorage>      mLocalStorage;
   nsCOMPtr<nsIDOMStorage>      mSessionStorage;
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -132,16 +132,20 @@ DOMInterfaces = {
 
 'BeforeUnloadEvent': {
     'nativeType': 'nsDOMBeforeUnloadEvent',
 },
 
 'AudioStreamTrack': {
 },
 
+'BarProp': {
+    'headerFile': 'mozilla/dom/BarProps.h',
+},
+
 'BiquadFilterNode': {
     'resultNotAddRefed': [ 'frequency', 'detune', 'q', 'gain' ],
 },
 
 'Blob': [
 {
     'headerFile': 'nsIDOMFile.h',
 },
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -517,16 +517,22 @@ class ThreadLocalJSRuntime
       MOZ_COUNT_CTOR(ThreadLocalJSRuntime);
   }
 
   nsresult Init()
   {
     mRuntime = JS_NewRuntime(sRuntimeHeapSize, JS_NO_HELPER_THREADS);
     NS_ENSURE_TRUE(mRuntime, NS_ERROR_OUT_OF_MEMORY);
 
+    /*
+     * Not setting this will cause JS_CHECK_RECURSION to report false
+     * positives
+     */
+    JS_SetNativeStackQuota(mRuntime, 128 * sizeof(size_t) * 1024); 
+
     mContext = JS_NewContext(mRuntime, 0);
     NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY);
 
     JSAutoRequest ar(mContext);
 
     mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, NULL);
     NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
 
--- a/dom/interfaces/base/domstubs.idl
+++ b/dom/interfaces/base/domstubs.idl
@@ -43,17 +43,16 @@ interface nsIDOMMediaList;
 
 // Base
 interface nsIDOMWindow;
 interface nsIDOMWindowCollection;
 interface nsIDOMPlugin;
 interface nsIDOMPluginArray;
 interface nsIDOMMimeType;
 interface nsIDOMMimeTypeArray;
-interface nsIDOMBarProp;
 interface nsIDOMNavigator;
 interface nsIDOMScreen;
 interface nsIDOMHistory;
 
 // Events
 interface nsIDOMEvent;
 interface nsIDOMEventTarget;
 interface nsIDOMEventListener;
--- a/dom/interfaces/base/moz.build
+++ b/dom/interfaces/base/moz.build
@@ -6,17 +6,16 @@
 
 XPIDL_SOURCES += [
     'domstubs.idl',
     'nsIBrowserDOMWindow.idl',
     'nsIContentPermissionPrompt.idl',
     'nsIContentPrefService.idl',
     'nsIContentPrefService2.idl',
     'nsIContentURIGrouper.idl',
-    'nsIDOMBarProp.idl',
     'nsIDOMCRMFObject.idl',
     'nsIDOMChromeWindow.idl',
     'nsIDOMClientInformation.idl',
     'nsIDOMClientRect.idl',
     'nsIDOMClientRectList.idl',
     'nsIDOMConstructor.idl',
     'nsIDOMGlobalObjectConstructor.idl',
     'nsIDOMGlobalPropertyInitializer.idl',
deleted file mode 100644
--- a/dom/interfaces/base/nsIDOMBarProp.idl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* -*- 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 "domstubs.idl"
-
-/**
- * The nsIDOMBarProp interface is the interface for controlling and
- * accessing the visibility of certain UI items (scrollbars, menubars,
- * toolbars, ...) through the DOM.
- */
-
-[scriptable, uuid(9eb2c150-1d56-11d3-8221-0060083a0bcf)]
-interface nsIDOMBarProp : nsISupports
-{
-           attribute boolean          visible;
-};
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -48,37 +48,43 @@ interface nsIDOMWindow : nsISupports
 
   /* The setter that takes a string argument needs to be special cased! */
   readonly attribute nsIDOMLocation                     location;
 
   readonly attribute nsIDOMHistory                      history;
 
 
   /* [replaceable] locationbar */
-  readonly attribute nsIDOMBarProp                      locationbar;
+  /* BarProp */
+  readonly attribute nsISupports                        locationbar;
 
   /* [replaceable] menubar */
-  readonly attribute nsIDOMBarProp                      menubar;
+  /* BarProp */
+  readonly attribute nsISupports                        menubar;
 
   /* [replaceable] personalbar */
-  readonly attribute nsIDOMBarProp                      personalbar;
+  /* BarProp */
+  readonly attribute nsISupports                        personalbar;
 
   /**
    * Accessor for the object that controls whether or not scrollbars
    * are shown in this window.
    *
    * This attribute is "replaceable" in JavaScript
    */
-  readonly attribute nsIDOMBarProp                      scrollbars;
+  /* BarProp */
+  readonly attribute nsISupports                        scrollbars;
 
   /* [replaceable] statusbar */
-  readonly attribute nsIDOMBarProp                      statusbar;
+  /* BarProp */
+  readonly attribute nsISupports                        statusbar;
 
   /* [replaceable] toolbar */
-  readonly attribute nsIDOMBarProp                      toolbar;
+  /* BarProp */
+  readonly attribute nsISupports                        toolbar;
 
   /* [replaceable] */
            attribute DOMString                          status;
 
   void                      close();
   void                      stop();
   void                      focus();
   void                      blur();
--- a/dom/plugins/base/nsIPluginTag.idl
+++ b/dom/plugins/base/nsIPluginTag.idl
@@ -1,30 +1,35 @@
 /* -*- 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 "nsISupports.idl"
-interface nsIDOMMimeType;
 
-[scriptable, uuid(87b4fcfc-417b-47f6-9c79-dfeb5e5a4840)]
+[scriptable, uuid(00ea1f72-a57a-49bb-ac57-478902d9228b)]
 interface nsIPluginTag : nsISupports
 {
   // enabledState is stored as one of the following as an integer in prefs,
   // so if new states are added, they must not renumber the existing states.
   const unsigned long STATE_DISABLED = 0;
   const unsigned long STATE_CLICKTOPLAY = 1;
   const unsigned long STATE_ENABLED = 2;
 
   readonly attribute AUTF8String description;
   readonly attribute AUTF8String filename;
   readonly attribute AUTF8String fullpath;
   readonly attribute AUTF8String version;
   readonly attribute AUTF8String name;
-           attribute boolean  blocklisted;
-  readonly attribute boolean  disabled;
-  readonly attribute boolean  clicktoplay;
+           attribute boolean blocklisted;
+  readonly attribute boolean disabled;
+  readonly attribute boolean clicktoplay;
            attribute unsigned long enabledState;
 
   void getMimeTypes([optional] out unsigned long aCount,
-                    [retval, array, size_is(aCount)] out nsIDOMMimeType aResults);
+                    [retval, array, size_is(aCount)] out wstring aResults);
+  void getMimeDescriptions([optional] out unsigned long aCount,
+                           [retval, array, size_is(aCount)]
+                           out wstring aResults);
+  void getExtensions([optional] out unsigned long aCount,
+                     [retval, array, size_is(aCount)]
+                     out wstring aResults);
 };
--- a/dom/plugins/base/nsPluginTags.cpp
+++ b/dom/plugins/base/nsPluginTags.cpp
@@ -69,43 +69,43 @@ GetBlocklistedPrefNameForPlugin(nsPlugin
   return MakePrefNameForPlugin("blocklisted", aTag);
 }
 
 NS_IMPL_ISUPPORTS1(DOMMimeTypeImpl, nsIDOMMimeType)
 
 /* nsPluginTag */
 
 nsPluginTag::nsPluginTag(nsPluginTag* aPluginTag)
-: mName(aPluginTag->mName),
-mDescription(aPluginTag->mDescription),
-mMimeTypes(aPluginTag->mMimeTypes),
-mMimeDescriptions(aPluginTag->mMimeDescriptions),
-mExtensions(aPluginTag->mExtensions),
-mLibrary(nullptr),
-mIsJavaPlugin(aPluginTag->mIsJavaPlugin),
-mIsFlashPlugin(aPluginTag->mIsFlashPlugin),
-mFileName(aPluginTag->mFileName),
-mFullPath(aPluginTag->mFullPath),
-mVersion(aPluginTag->mVersion),
-mLastModifiedTime(0),
-mNiceFileName()
+  : mName(aPluginTag->mName),
+    mDescription(aPluginTag->mDescription),
+    mMimeTypes(aPluginTag->mMimeTypes),
+    mMimeDescriptions(aPluginTag->mMimeDescriptions),
+    mExtensions(aPluginTag->mExtensions),
+    mLibrary(nullptr),
+    mIsJavaPlugin(aPluginTag->mIsJavaPlugin),
+    mIsFlashPlugin(aPluginTag->mIsFlashPlugin),
+    mFileName(aPluginTag->mFileName),
+    mFullPath(aPluginTag->mFullPath),
+    mVersion(aPluginTag->mVersion),
+    mLastModifiedTime(0),
+    mNiceFileName()
 {
 }
 
 nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo)
-: mName(aPluginInfo->fName),
-mDescription(aPluginInfo->fDescription),
-mLibrary(nullptr),
-mIsJavaPlugin(false),
-mIsFlashPlugin(false),
-mFileName(aPluginInfo->fFileName),
-mFullPath(aPluginInfo->fFullPath),
-mVersion(aPluginInfo->fVersion),
-mLastModifiedTime(0),
-mNiceFileName()
+  : mName(aPluginInfo->fName),
+    mDescription(aPluginInfo->fDescription),
+    mLibrary(nullptr),
+    mIsJavaPlugin(false),
+    mIsFlashPlugin(false),
+    mFileName(aPluginInfo->fFileName),
+    mFullPath(aPluginInfo->fFullPath),
+    mVersion(aPluginInfo->fVersion),
+    mLastModifiedTime(0),
+    mNiceFileName()
 {
   InitMime(aPluginInfo->fMimeTypeArray,
            aPluginInfo->fMimeDescriptionArray,
            aPluginInfo->fExtensionArray,
            aPluginInfo->fVariantCount);
   EnsureMembersAreUTF8();
 }
 
@@ -115,28 +115,29 @@ nsPluginTag::nsPluginTag(const char* aNa
                          const char* aFullPath,
                          const char* aVersion,
                          const char* const* aMimeTypes,
                          const char* const* aMimeDescriptions,
                          const char* const* aExtensions,
                          int32_t aVariants,
                          int64_t aLastModifiedTime,
                          bool aArgsAreUTF8)
-: mName(aName),
-mDescription(aDescription),
-mLibrary(nullptr),
-mIsJavaPlugin(false),
-mIsFlashPlugin(false),
-mFileName(aFileName),
-mFullPath(aFullPath),
-mVersion(aVersion),
-mLastModifiedTime(aLastModifiedTime),
-mNiceFileName()
+  : mName(aName),
+    mDescription(aDescription),
+    mLibrary(nullptr),
+    mIsJavaPlugin(false),
+    mIsFlashPlugin(false),
+    mFileName(aFileName),
+    mFullPath(aFullPath),
+    mVersion(aVersion),
+    mLastModifiedTime(aLastModifiedTime),
+    mNiceFileName()
 {
-  InitMime(aMimeTypes, aMimeDescriptions, aExtensions, static_cast<uint32_t>(aVariants));
+  InitMime(aMimeTypes, aMimeDescriptions, aExtensions,
+           static_cast<uint32_t>(aVariants));
   if (!aArgsAreUTF8)
     EnsureMembersAreUTF8();
 }
 
 nsPluginTag::~nsPluginTag()
 {
   NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
 }
@@ -426,29 +427,61 @@ nsPluginTag::SetPluginState(PluginState 
 {
   MOZ_STATIC_ASSERT((uint32_t)nsPluginTag::ePluginState_Disabled == nsIPluginTag::STATE_DISABLED, "nsPluginTag::ePluginState_Disabled must match nsIPluginTag::STATE_DISABLED");
   MOZ_STATIC_ASSERT((uint32_t)nsPluginTag::ePluginState_Clicktoplay == nsIPluginTag::STATE_CLICKTOPLAY, "nsPluginTag::ePluginState_Clicktoplay must match nsIPluginTag::STATE_CLICKTOPLAY");
   MOZ_STATIC_ASSERT((uint32_t)nsPluginTag::ePluginState_Enabled == nsIPluginTag::STATE_ENABLED, "nsPluginTag::ePluginState_Enabled must match nsIPluginTag::STATE_ENABLED");
   SetEnabledState((uint32_t)state);
 }
 
 NS_IMETHODIMP
-nsPluginTag::GetMimeTypes(uint32_t* aCount, nsIDOMMimeType*** aResults)
+nsPluginTag::GetMimeTypes(uint32_t* aCount, PRUnichar*** aResults)
 {
   uint32_t count = mMimeTypes.Length();
-  *aResults = static_cast<nsIDOMMimeType**>
+  *aResults = static_cast<PRUnichar**>
                          (nsMemory::Alloc(count * sizeof(**aResults)));
   if (!*aResults)
     return NS_ERROR_OUT_OF_MEMORY;
   *aCount = count;
 
   for (uint32_t i = 0; i < count; i++) {
-    nsIDOMMimeType* mimeType = new DOMMimeTypeImpl(this, i);
-    (*aResults)[i] = mimeType;
-    NS_ADDREF((*aResults)[i]);
+    (*aResults)[i] = ToNewUnicode(mMimeTypes[i]);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPluginTag::GetMimeDescriptions(uint32_t* aCount, PRUnichar*** aResults)
+{
+  uint32_t count = mMimeDescriptions.Length();
+  *aResults = static_cast<PRUnichar**>
+                         (nsMemory::Alloc(count * sizeof(**aResults)));
+  if (!*aResults)
+    return NS_ERROR_OUT_OF_MEMORY;
+  *aCount = count;
+
+  for (uint32_t i = 0; i < count; i++) {
+    (*aResults)[i] = ToNewUnicode(mMimeDescriptions[i]);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPluginTag::GetExtensions(uint32_t* aCount, PRUnichar*** aResults)
+{
+  uint32_t count = mExtensions.Length();
+  *aResults = static_cast<PRUnichar**>
+                         (nsMemory::Alloc(count * sizeof(**aResults)));
+  if (!*aResults)
+    return NS_ERROR_OUT_OF_MEMORY;
+  *aCount = count;
+
+  for (uint32_t i = 0; i < count; i++) {
+    (*aResults)[i] = ToNewUnicode(mExtensions[i]);
   }
 
   return NS_OK;
 }
 
 bool
 nsPluginTag::HasSameNameAndMimes(const nsPluginTag *aPluginTag) const
 {
--- a/dom/plugins/test/mochitest/test_refresh_navigator_plugins.html
+++ b/dom/plugins/test/mochitest/test_refresh_navigator_plugins.html
@@ -32,32 +32,32 @@
         if (plugin.name == navTestPlugin.name) {
           tagTestPlugin = plugin;
           break;
         }
       }
       ok(tagTestPlugin, "plugin tags should have Test Plug-in");
       var mimeType = tagTestPlugin.getMimeTypes()[0];
       ok(mimeType, "should have a MIME type for Test Plug-in");
-      ok(navigator.mimeTypes[mimeType.type], "navigator.mimeTypes should have an entry for '" + mimeType.type + "'");
+      ok(navigator.mimeTypes[mimeType], "navigator.mimeTypes should have an entry for '" + mimeType + "'");
       ok(!tagTestPlugin.disabled, "test plugin should not be disabled");
 
       nextTest = testPart2;
       tagTestPlugin.enabledState = Components.interfaces.nsIPluginTag.STATE_DISABLED;
 
       function testPart2() {
         var navTestPlugin = navigator.plugins.namedItem("Test Plug-in");
         ok(!navTestPlugin, "now navigator.plugins should not have Test Plug-in");
-        ok(!navigator.mimeTypes[mimeType.type], "now navigator.mimeTypes should not have an entry for '" + mimeType.type + "'");
+        ok(!navigator.mimeTypes[mimeType], "now navigator.mimeTypes should not have an entry for '" + mimeType + "'");
 
         nextTest = testPart3;
         tagTestPlugin.enabledState = Components.interfaces.nsIPluginTag.STATE_ENABLED;
       }
 
       function testPart3() {
         ok(navTestPlugin, "now navigator.plugins should have Test Plug-in again");
-        ok(navigator.mimeTypes[mimeType.type], "now navigator.mimeTypes should have an entry for '" + mimeType.type + "' again");
+        ok(navigator.mimeTypes[mimeType], "now navigator.mimeTypes should have an entry for '" + mimeType + "' again");
         obsService.removeObserver(observer, "plugin-info-updated");
         SimpleTest.finish();
       }
     </script>
   </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/webidl/BarProp.webidl
@@ -0,0 +1,11 @@
+/* -*- 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/.
+ */
+
+interface BarProp
+{
+  [Throws]
+           attribute boolean visible;
+};
--- a/dom/webidl/HTMLImageElement.webidl
+++ b/dom/webidl/HTMLImageElement.webidl
@@ -50,16 +50,26 @@ partial interface HTMLImageElement {
            [SetterThrows]
            attribute unsigned long vspace;
            [SetterThrows]
            attribute DOMString longDesc;
 
   [TreatNullAs=EmptyString,SetterThrows] attribute DOMString border;
 };
 
+// Mozilla extensions.
+partial interface HTMLImageElement {
+           attribute DOMString lowsrc;
+
+  // These attributes are offsets from the closest view (to mimic
+  // NS4's "offset-from-layer" behavior).
+  readonly attribute long x;
+  readonly attribute long y;
+};
+
 [NoInterfaceObject]
 interface MozImageLoadingContent {
   // Mirrored chrome-only nsIImageLoadingContent methods.  Please make sure
   // to update this list if nsIImageLoadingContent changes.
   [ChromeOnly]
   const long UNKNOWN_REQUEST = -1;
   [ChromeOnly]
   const long CURRENT_REQUEST = 0;
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -18,16 +18,17 @@ webidl_files = \
   AudioBufferSourceNode.webidl \
   AudioContext.webidl \
   AudioDestinationNode.webidl \
   AudioListener.webidl \
   AudioNode.webidl \
   AudioParam.webidl \
   AudioStreamTrack.webidl \
   AudioProcessingEvent.webidl \
+  BarProp.webidl \
   BatteryManager.webidl \
   BeforeUnloadEvent.webidl \
   BiquadFilterNode.webidl \
   Blob.webidl \
   CanvasRenderingContext2D.webidl \
   CaretPosition.webidl \
   CDATASection.webidl \
   CFStateChangeEvent.webidl \
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -145,19 +145,19 @@ public:
    * Ensure that a suitable texture host exists in this compsitable.
    *
    * Only used with ContentHostIncremental.
    *
    * No SurfaceDescriptor or TextureIdentifier is provider as we
    * don't have a single surface for the texture contents, and we
    * need to allocate our own one to be updated later.
    */
-  virtual void EnsureTextureHost(ISurfaceAllocator* aAllocator,
-                                 const TextureInfo& aTextureInfo,
-                                 const nsIntRect& aBufferRect)
+  virtual void EnsureTextureHostIncremental(ISurfaceAllocator* aAllocator,
+                                            const TextureInfo& aTextureInfo,
+                                            const nsIntRect& aBufferRect)
   {
     MOZ_ASSERT(false, "should be implemented or not used");
   }
 
   virtual TextureHost* GetTextureHost() { return nullptr; }
 
   virtual LayerRenderState GetRenderState() = 0;
 
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -458,19 +458,19 @@ ContentHostDoubleBuffered::UpdateThebes(
   //
   // NB: we rely here on the fact that mValidRegion is initialized to
   // empty, and that the first time Swap() is called we don't have a
   // valid front buffer that we're going to return to content.
   mValidRegionForNextBackBuffer = aOldValidRegionBack;
 }
 
 void
-ContentHostIncremental::EnsureTextureHost(ISurfaceAllocator* aAllocator,
-                                          const TextureInfo& aTextureInfo,
-                                          const nsIntRect& aBufferRect)
+ContentHostIncremental::EnsureTextureHostIncremental(ISurfaceAllocator* aAllocator,
+                                                     const TextureInfo& aTextureInfo,
+                                                     const nsIntRect& aBufferRect)
 {
   mUpdateList.AppendElement(new TextureCreationRequest(aTextureInfo,
                                                        aBufferRect));
   mDeAllocator = aAllocator;
 }
 
 void
 ContentHostIncremental::UpdateIncremental(TextureIdentifier aTextureId,
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -218,19 +218,19 @@ class ContentHostIncremental : public Co
 public:
   ContentHostIncremental(const TextureInfo& aTextureInfo)
     : ContentHostBase(aTextureInfo)
     , mDeAllocator(nullptr)
   {}
 
   virtual CompositableType GetType() { return BUFFER_CONTENT; }
 
-  virtual void EnsureTextureHost(ISurfaceAllocator* aAllocator,
-                                 const TextureInfo& aTextureInfo,
-                                 const nsIntRect& aBufferRect) MOZ_OVERRIDE;
+  virtual void EnsureTextureHostIncremental(ISurfaceAllocator* aAllocator,
+                                            const TextureInfo& aTextureInfo,
+                                            const nsIntRect& aBufferRect) MOZ_OVERRIDE;
 
   virtual void EnsureTextureHost(TextureIdentifier aTextureId,
                                  const SurfaceDescriptor& aSurface,
                                  ISurfaceAllocator* aAllocator,
                                  const TextureInfo& aTextureInfo)
   {
     NS_RUNTIMEABORT("Shouldn't call this");
   }
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -41,19 +41,19 @@ CompositableParentManager::ReceiveCompos
     case CompositableOperation::TOpCreatedIncrementalTexture: {
       MOZ_LAYERS_LOG(("[ParentSide] Created texture"));
       const OpCreatedIncrementalTexture& op = aEdit.get_OpCreatedIncrementalTexture();
 
       CompositableParent* compositableParent =
         static_cast<CompositableParent*>(op.compositableParent());
       CompositableHost* compositable = compositableParent->GetCompositableHost();
 
-      compositable->EnsureTextureHost(compositableParent->GetCompositableManager(),
-                                      op.textureInfo(),
-                                      op.bufferRect());
+      compositable->EnsureTextureHostIncremental(compositableParent->GetCompositableManager(),
+                                                 op.textureInfo(),
+                                                 op.bufferRect());
       break;
     }
     case CompositableOperation::TOpDestroyThebesBuffer: {
       MOZ_LAYERS_LOG(("[ParentSide] Created double buffer"));
       const OpDestroyThebesBuffer& op = aEdit.get_OpDestroyThebesBuffer();
       CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent());
       ContentHostBase* content = static_cast<ContentHostBase*>(compositableParent->GetCompositableHost());
       content->DestroyTextures();
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -75,16 +75,34 @@ NS_MEMORY_REPORTER_IMPLEMENT(
     KIND_OTHER,
     UNITS_BYTES,
     cairo_d2d_get_image_surface_cache_usage,
     "Memory used by the Direct2D internal surface cache.")
 
 namespace
 {
 
+bool OncePreferenceDirect2DDisabled()
+{
+  static int preferenceValue = -1;
+  if (preferenceValue < 0) {
+    preferenceValue = Preferences::GetBool("gfx.direct2d.disabled", false);
+  }
+  return !!preferenceValue;
+}
+
+bool OncePreferenceDirect2DForceEnabled()
+{
+  static int preferenceValue = -1;
+  if (preferenceValue < 0) {
+    preferenceValue = Preferences::GetBool("gfx.direct2d.force-enabled", false);
+  }
+  return !!preferenceValue;
+}
+
 int64_t GetD2DSurfaceVramUsage() {
   cairo_device_t *device =
       gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
   if (device) {
       return cairo_d2d_get_surface_vram_usage(device);
   }
   return 0;
 }
@@ -413,18 +431,20 @@ gfxWindowsPlatform::UpdateRenderMode()
         int32_t status;
         if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT2D, &status))) {
             if (status != nsIGfxInfo::FEATURE_NO_INFO) {
                 d2dBlocked = true;
             }
         }
     }
 
-    d2dDisabled = Preferences::GetBool("gfx.direct2d.disabled", false);
-    d2dForceEnabled = Preferences::GetBool("gfx.direct2d.force-enabled", false);
+    // These will only be evaluated once, and any subsequent changes to
+    // the preferences will be ignored until restart.
+    d2dDisabled = OncePreferenceDirect2DDisabled();
+    d2dForceEnabled = OncePreferenceDirect2DForceEnabled();
 
 #ifdef MOZ_METRO
     // In Metro mode there is no fallback available
     d2dForceEnabled |= IsRunningInWindowsMetro();
 #endif
 
     bool tryD2D = !d2dBlocked || d2dForceEnabled;
 
--- a/ipc/chromium/src/base/process_util_win.cc
+++ b/ipc/chromium/src/base/process_util_win.cc
@@ -1,32 +1,62 @@
 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// We need extended process and thread attribute support
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+
 #include "base/process_util.h"
 
 #include <windows.h>
 #include <winternl.h>
 #include <psapi.h>
 
 #include "base/debug_util.h"
 #include "base/histogram.h"
 #include "base/logging.h"
 #include "base/scoped_handle_win.h"
 #include "base/scoped_ptr.h"
+#include "base/win_util.h"
 
 namespace {
 
 // System pagesize. This value remains constant on x86/64 architectures.
 const int PAGESIZE_KB = 4;
 
 // HeapSetInformation function pointer.
 typedef BOOL (WINAPI* HeapSetFn)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T);
 
+typedef BOOL (WINAPI * InitializeProcThreadAttributeListFn)(
+  LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
+  DWORD dwAttributeCount,
+  DWORD dwFlags,
+  PSIZE_T lpSize
+);
+
+typedef BOOL (WINAPI * DeleteProcThreadAttributeListFn)(
+  LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList
+);
+
+typedef BOOL (WINAPI * UpdateProcThreadAttributeFn)(
+  LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
+  DWORD dwFlags,
+  DWORD_PTR Attribute,
+  PVOID lpValue,
+  SIZE_T cbSize,
+  PVOID lpPreviousValue,
+  PSIZE_T lpReturnSize
+);
+
+static InitializeProcThreadAttributeListFn InitializeProcThreadAttributeListPtr;
+static DeleteProcThreadAttributeListFn DeleteProcThreadAttributeListPtr;
+static UpdateProcThreadAttributeFn UpdateProcThreadAttributePtr;
+
 static mozilla::EnvironmentLog gProcessLog("MOZ_PROCESS_LOG");
 
 }  // namespace
 
 namespace base {
 
 ProcessId GetCurrentProcId() {
   return ::GetCurrentProcessId();
@@ -147,27 +177,159 @@ ProcessId GetProcId(ProcessHandle proces
       return id;
   }
 
   // We're screwed.
   NOTREACHED();
   return 0;
 }
 
+// from sandbox_policy_base.cc in a later version of the chromium ipc code...
+bool IsInheritableHandle(HANDLE handle) {
+  if (!handle)
+    return false;
+  if (handle == INVALID_HANDLE_VALUE)
+    return false;
+  // File handles (FILE_TYPE_DISK) and pipe handles are known to be
+  // inheritable.  Console handles (FILE_TYPE_CHAR) are not
+  // inheritable via PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
+  DWORD handle_type = GetFileType(handle);
+  return handle_type == FILE_TYPE_DISK || handle_type == FILE_TYPE_PIPE;
+}
+
+void LoadThreadAttributeFunctions() {
+  HMODULE kernel32 = GetModuleHandle(L"kernel32.dll");
+  InitializeProcThreadAttributeListPtr =
+    reinterpret_cast<InitializeProcThreadAttributeListFn>
+    (GetProcAddress(kernel32, "InitializeProcThreadAttributeList"));
+  DeleteProcThreadAttributeListPtr =
+    reinterpret_cast<DeleteProcThreadAttributeListFn>
+    (GetProcAddress(kernel32, "DeleteProcThreadAttributeList"));
+  UpdateProcThreadAttributePtr =
+    reinterpret_cast<UpdateProcThreadAttributeFn>
+    (GetProcAddress(kernel32, "UpdateProcThreadAttribute"));
+}
+
+// Creates and returns a "thread attribute list" to pass to the child process.
+// On return, is a pointer to a THREAD_ATTRIBUTE_LIST or NULL if either the
+// functions we need aren't available (eg, XP or earlier) or the functions we
+// need failed.
+// The result of this function must be passed to FreeThreadAttributeList.
+// Note that the pointer to the HANDLE array ends up embedded in the result of
+// this function and must stay alive until FreeThreadAttributeList is called,
+// hence it is passed in so the owner is the caller of this function.
+LPPROC_THREAD_ATTRIBUTE_LIST CreateThreadAttributeList(HANDLE *handlesToInherit,
+                                                       int handleCount) {
+  if (!InitializeProcThreadAttributeListPtr ||
+      !DeleteProcThreadAttributeListPtr ||
+      !UpdateProcThreadAttributePtr)
+    LoadThreadAttributeFunctions();
+  // shouldn't happen as we are only called for Vista+, but better safe than sorry...
+  if (!InitializeProcThreadAttributeListPtr ||
+      !DeleteProcThreadAttributeListPtr ||
+      !UpdateProcThreadAttributePtr)
+    return NULL;
+
+  SIZE_T threadAttrSize;
+  LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList;
+
+  if (!(*InitializeProcThreadAttributeListPtr)(NULL, 1, 0, &threadAttrSize) &&
+      GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+    goto fail;
+  lpAttributeList = reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>
+                              (malloc(threadAttrSize));
+  if (!lpAttributeList ||
+      !(*InitializeProcThreadAttributeListPtr)(lpAttributeList, 1, 0, &threadAttrSize))
+    goto fail;
+
+  if (!(*UpdateProcThreadAttributePtr)(lpAttributeList,
+                  0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
+                  handlesToInherit,
+                  sizeof(handlesToInherit[0]) * handleCount,
+                  NULL, NULL)) {
+    (*DeleteProcThreadAttributeListPtr)(lpAttributeList);
+    goto fail;
+  }
+  return lpAttributeList;
+
+fail:
+  if (lpAttributeList)
+    free(lpAttributeList);
+  return NULL;
+}
+
+// Frees the data returned by CreateThreadAttributeList.
+void FreeThreadAttributeList(LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList) {
+  // must be impossible to get a NULL DeleteProcThreadAttributeListPtr, as
+  // we already checked it existed when creating the data we are now freeing.
+  (*DeleteProcThreadAttributeListPtr)(lpAttributeList);
+  free(lpAttributeList);
+}
+
 bool LaunchApp(const std::wstring& cmdline,
                bool wait, bool start_hidden, ProcessHandle* process_handle) {
-  STARTUPINFO startup_info = {0};
+
+  // We want to inherit the std handles so dump() statements and assertion
+  // messages in the child process can be seen - but we *do not* want to
+  // blindly have all handles inherited.  Vista and later has a technique
+  // where only specified handles are inherited - so we use this technique if
+  // we can.  If that technique isn't available (or it fails), we just don't
+  // inherit anything.  This means that dump() etc isn't going to be seen on
+  // XP release builds, but that's OK (developers who really care can run a
+  // debug build on XP, where the processes are marked as "console" apps, so
+  // things work without these hoops)
+  DWORD dwCreationFlags = 0;
+  BOOL bInheritHandles = FALSE;
+  // We use a STARTUPINFOEX, but if we can't do the thread attribute thing, we
+  // just pass the size of a STARTUPINFO.
+  STARTUPINFOEX startup_info_ex;
+  ZeroMemory(&startup_info_ex, sizeof(startup_info_ex));
+  STARTUPINFO &startup_info = startup_info_ex.StartupInfo;
   startup_info.cb = sizeof(startup_info);
   startup_info.dwFlags = STARTF_USESHOWWINDOW;
   startup_info.wShowWindow = start_hidden ? SW_HIDE : SW_SHOW;
+
+  LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL;
+  // Don't even bother trying pre-Vista...
+  if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
+    // setup our handle array first - if we end up with no handles that can
+    // be inherited we can avoid trying to do the ThreadAttributeList dance...
+    HANDLE handlesToInherit[2];
+    int handleCount = 0;
+    HANDLE stdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
+    HANDLE stdErr = ::GetStdHandle(STD_ERROR_HANDLE);
+
+    if (IsInheritableHandle(stdOut))
+      handlesToInherit[handleCount++] = stdOut;
+    if (stdErr != stdOut && IsInheritableHandle(stdErr))
+      handlesToInherit[handleCount++] = stdErr;
+
+    if (handleCount)
+      lpAttributeList = CreateThreadAttributeList(handlesToInherit, handleCount);
+  }
+
+  if (lpAttributeList) {
+    // it's safe to inherit handles, so arrange for that...
+    startup_info.cb = sizeof(startup_info_ex);
+    startup_info.dwFlags |= STARTF_USESTDHANDLES;
+    startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+    startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+    startup_info.hStdInput = INVALID_HANDLE_VALUE;
+    startup_info_ex.lpAttributeList = lpAttributeList;
+    dwCreationFlags |= EXTENDED_STARTUPINFO_PRESENT;
+    bInheritHandles = TRUE;
+  }
   PROCESS_INFORMATION process_info;
-  if (!CreateProcess(NULL,
+  BOOL createdOK = CreateProcess(NULL,
                      const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL,
-                     FALSE, 0, NULL, NULL,
-                     &startup_info, &process_info))
+                     bInheritHandles, dwCreationFlags, NULL, NULL,
+                     &startup_info, &process_info);
+  if (lpAttributeList)
+    FreeThreadAttributeList(lpAttributeList);
+  if (!createdOK)
     return false;
 
   gProcessLog.print("==> process %d launched child process %d\n",
                     GetCurrentProcId(),
                     process_info.dwProcessId);
 
   // Handles must be closed or they will leak
   CloseHandle(process_info.hThread);
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -5590,16 +5590,19 @@ EmitDefaults(JSContext *cx, BytecodeEmit
         if (!BindNameToSlot(cx, bce, arg))
             return false;
         if (!EmitVarOp(cx, arg, JSOP_GETARG, bce))
             return false;
         if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
             return false;
         if (Emit1(cx, bce, JSOP_STRICTEQ) < 0)
             return false;
+        // Emit source note to enable ion compilation.
+        if (NewSrcNote(cx, bce, SRC_IF) < 0)
+            return false;
         ptrdiff_t jump = EmitJump(cx, bce, JSOP_IFEQ, 0);
         if (jump < 0)
             return false;
         if (!EmitTree(cx, bce, arg->expr()))
             return false;
         if (!EmitVarOp(cx, arg, JSOP_SETARG, bce))
             return false;
         if (Emit1(cx, bce, JSOP_POP) < 0)
--- a/js/src/ion/Bailouts.cpp
+++ b/js/src/ion/Bailouts.cpp
@@ -153,17 +153,18 @@ ion::EnsureHasScopeObjects(JSContext *cx
 
 bool
 ion::CheckFrequentBailouts(JSContext *cx, JSScript *script)
 {
     // Invalidate if this script keeps bailing out without invalidation. Next time
     // we compile this script LICM will be disabled.
 
     if (script->hasIonScript() &&
-        script->ionScript()->numBailouts() >= js_IonOptions.frequentBailoutThreshold)
+        script->ionScript()->numBailouts() >= js_IonOptions.frequentBailoutThreshold &&
+        !script->hadFrequentBailouts)
     {
         script->hadFrequentBailouts = true;
 
         IonSpew(IonSpew_Invalidate, "Invalidating due to too many bailouts");
 
         if (!Invalidate(cx, script))
             return false;
     }
--- a/js/src/ion/BaselineCompiler.cpp
+++ b/js/src/ion/BaselineCompiler.cpp
@@ -2345,30 +2345,59 @@ BaselineCompiler::emit_JSOP_ENTERLET1()
 {
     return emitEnterBlock();
 }
 
 typedef bool (*LeaveBlockFn)(JSContext *, BaselineFrame *);
 static const VMFunction LeaveBlockInfo = FunctionInfo<LeaveBlockFn>(ion::LeaveBlock);
 
 bool
-BaselineCompiler::emit_JSOP_LEAVEBLOCK()
+BaselineCompiler::emitLeaveBlock()
 {
     // Call a stub to pop the block from the block chain.
     prepareVMCall();
 
     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
     pushArg(R0.scratchReg());
 
-    if (!callVM(LeaveBlockInfo))
+    return callVM(LeaveBlockInfo);
+}
+
+bool
+BaselineCompiler::emit_JSOP_LEAVEBLOCK()
+{
+    if (!emitLeaveBlock())
         return false;
 
-    // Pop slots pushed by ENTERBLOCK.
-    size_t n = StackUses(script, pc);
-    frame.popn(n);
+    // Pop slots pushed by JSOP_ENTERBLOCK.
+    frame.popn(GET_UINT16(pc));
+    return true;
+}
+
+bool
+BaselineCompiler::emit_JSOP_LEAVEBLOCKEXPR()
+{
+    if (!emitLeaveBlock())
+        return false;
+
+    // Pop slots pushed by JSOP_ENTERBLOCK, but leave the topmost value
+    // on the stack.
+    frame.popRegsAndSync(1);
+    frame.popn(GET_UINT16(pc));
+    frame.push(R0);
+    return true;
+}
+
+bool
+BaselineCompiler::emit_JSOP_LEAVEFORLETIN()
+{
+    if (!emitLeaveBlock())
+        return false;
+
+    // Another op will pop the slots (after the enditer).
     return true;
 }
 
 typedef bool (*GetAndClearExceptionFn)(JSContext *, MutableHandleValue);
 static const VMFunction GetAndClearExceptionInfo =
     FunctionInfo<GetAndClearExceptionFn>(GetAndClearException);
 
 bool
--- a/js/src/ion/BaselineCompiler.h
+++ b/js/src/ion/BaselineCompiler.h
@@ -150,16 +150,18 @@ namespace ion {
     _(JSOP_TYPEOFEXPR)         \
     _(JSOP_SETCALL)            \
     _(JSOP_THROW)              \
     _(JSOP_TRY)                \
     _(JSOP_ENTERBLOCK)         \
     _(JSOP_ENTERLET0)          \
     _(JSOP_ENTERLET1)          \
     _(JSOP_LEAVEBLOCK)         \
+    _(JSOP_LEAVEBLOCKEXPR)     \
+    _(JSOP_LEAVEFORLETIN)      \
     _(JSOP_EXCEPTION)          \
     _(JSOP_DEBUGGER)           \
     _(JSOP_ARGUMENTS)          \
     _(JSOP_RUNONCE)            \
     _(JSOP_REST)               \
     _(JSOP_TOID)               \
     _(JSOP_TABLESWITCH)        \
     _(JSOP_ITER)               \
@@ -245,16 +247,17 @@ class BaselineCompiler : public Baseline
     bool emitCall();
 
     bool emitInitPropGetterSetter();
     bool emitInitElemGetterSetter();
 
     bool emitFormalArgAccess(uint32_t arg, bool get);
 
     bool emitEnterBlock();
+    bool emitLeaveBlock();
 
     bool addPCMappingEntry(bool addIndexEntry);
 
     void getScopeCoordinateObject(Register reg);
     Address getScopeCoordinateAddressFromObject(Register objReg, Register reg);
     Address getScopeCoordinateAddress(Register reg);
 };
 
--- a/js/src/ion/shared/MacroAssembler-x86-shared.h
+++ b/js/src/ion/shared/MacroAssembler-x86-shared.h
@@ -199,17 +199,17 @@ class MacroAssemblerX86Shared : public A
     void jump(RepatchLabel *label) {
         jmp(label);
     }
     void jump(Register reg) {
         jmp(Operand(reg));
     }
 
     void convertInt32ToDouble(const Register &src, const FloatRegister &dest) {
-        cvtsi2sd(Operand(src), dest);
+        cvtsi2sd(src, dest);
     }
     void convertInt32ToDouble(const Address &src, FloatRegister dest) {
         cvtsi2sd(Operand(src), dest);
     }
     Condition testDoubleTruthy(bool truthy, const FloatRegister &reg) {
         xorpd(ScratchFloatReg, ScratchFloatReg);
         ucomisd(ScratchFloatReg, reg);
         return truthy ? NonZero : Zero;
--- a/js/src/ion/x64/MacroAssembler-x64.h
+++ b/js/src/ion/x64/MacroAssembler-x64.h
@@ -161,17 +161,17 @@ class MacroAssemblerX64 : public MacroAs
     void loadValue(const BaseIndex &src, ValueOperand val) {
         loadValue(Operand(src), val);
     }
     void tagValue(JSValueType type, Register payload, ValueOperand dest) {
         JS_ASSERT(dest.valueReg() != ScratchReg);
         if (payload != dest.valueReg())
             movq(payload, dest.valueReg());
         mov(ImmShiftedTag(type), ScratchReg);
-        orq(Operand(ScratchReg), dest.valueReg());
+        orq(ScratchReg, dest.valueReg());
     }
     void pushValue(ValueOperand val) {
         push(val.valueReg());
     }
     void Push(const ValueOperand &val) {
         pushValue(val);
         framePushed_ += sizeof(Value);
     }
@@ -543,17 +543,17 @@ class MacroAssemblerX64 : public MacroAs
     void loadPtr(const Address &address, Register dest) {
         movq(Operand(address), dest);
     }
     void loadPtr(const Operand &src, Register dest) {
         movq(src, dest);
     }
     void loadPtr(const BaseIndex &src, Register dest) {
         movq(Operand(src), dest);
-	}
+    }
     void loadPrivate(const Address &src, Register dest) {
         loadPtr(src, dest);
         shlq(Imm32(1), dest);
     }
     void storePtr(ImmWord imm, const Address &address) {
         mov(imm, ScratchReg);
         movq(ScratchReg, Operand(address));
     }
@@ -617,17 +617,17 @@ class MacroAssemblerX64 : public MacroAs
 
     // Extracts the tag of a value and places it in ScratchReg.
     Register splitTagForTest(const ValueOperand &value) {
         splitTag(value, ScratchReg);
         return ScratchReg;
     }
     void cmpTag(const ValueOperand &operand, ImmTag tag) {
         Register reg = splitTagForTest(operand);
-        cmpl(Operand(reg), tag);
+        cmpl(reg, tag);
     }
 
     void branchTestUndefined(Condition cond, Register tag, Label *label) {
         cond = testUndefined(cond, tag);
         j(cond, label);
     }
     void branchTestInt32(Condition cond, Register tag, Label *label) {
         cond = testInt32(cond, tag);
@@ -783,17 +783,17 @@ class MacroAssemblerX64 : public MacroAs
     void boxNonDouble(JSValueType type, const Register &src, const ValueOperand &dest) {
         JS_ASSERT(src != dest.valueReg());
         boxValue(type, src, dest.valueReg());
     }
 
     // Note that the |dest| register here may be ScratchReg, so we shouldn't
     // use it.
     void unboxInt32(const ValueOperand &src, const Register &dest) {
-        movl(Operand(src.valueReg()), dest);
+        movl(src.valueReg(), dest);
     }
     void unboxInt32(const Operand &src, const Register &dest) {
         movl(src, dest);
     }
     void unboxInt32(const Address &src, const Register &dest) {
         unboxInt32(Operand(src), dest);
     }
     void unboxDouble(const Address &src, const FloatRegister &dest) {
@@ -806,27 +806,27 @@ class MacroAssemblerX64 : public MacroAs
     void unboxArgObjMagic(const Operand &src, const Register &dest) {
         xorq(dest, dest);
     }
     void unboxArgObjMagic(const Address &src, const Register &dest) {
         unboxArgObjMagic(Operand(src), dest);
     }
 
     void unboxBoolean(const ValueOperand &src, const Register &dest) {
-        movl(Operand(src.valueReg()), dest);
+        movl(src.valueReg(), dest);
     }
     void unboxBoolean(const Operand &src, const Register &dest) {
         movl(src, dest);
     }
     void unboxBoolean(const Address &src, const Register &dest) {
         unboxBoolean(Operand(src), dest);
     }
 
     void unboxMagic(const ValueOperand &src, const Register &dest) {
-        movl(Operand(src.valueReg()), dest);
+        movl(src.valueReg(), dest);
     }
 
     void unboxDouble(const ValueOperand &src, const FloatRegister &dest) {
         movqsd(src.valueReg(), dest);
     }
     void unboxPrivate(const ValueOperand &src, const Register dest) {
         movq(src.valueReg(), dest);
         shlq(Imm32(1), dest);
@@ -908,20 +908,20 @@ class MacroAssemblerX64 : public MacroAs
             bind(&end);
         } else {
             unboxNonDouble(src, dest.gpr());
         }
     }
 
     // These two functions use the low 32-bits of the full value register.
     void boolValueToDouble(const ValueOperand &operand, const FloatRegister &dest) {
-        cvtsi2sd(Operand(operand.valueReg()), dest);
+        cvtsi2sd(operand.valueReg(), dest);
     }
     void int32ValueToDouble(const ValueOperand &operand, const FloatRegister &dest) {
-        cvtsi2sd(Operand(operand.valueReg()), dest);
+        cvtsi2sd(operand.valueReg(), dest);
     }
 
     void loadConstantDouble(double d, const FloatRegister &dest) {
         union DoublePun {
             uint64_t u;
             double d;
         } pun;
         pun.d = d;
--- a/js/src/ion/x86/MacroAssembler-x86.h
+++ b/js/src/ion/x86/MacroAssembler-x86.h
@@ -726,17 +726,17 @@ class MacroAssemblerX86 : public MacroAs
             movd(scratch, ScratchFloatReg);
             unpcklps(ScratchFloatReg, dest);
         }
     }
     void unboxValue(const ValueOperand &src, AnyRegister dest) {
         if (dest.isFloat()) {
             Label notInt32, end;
             branchTestInt32(Assembler::NotEqual, src, &notInt32);
-            cvtsi2sd(Operand(src.payloadReg()), dest.fpu());
+            cvtsi2sd(src.payloadReg(), dest.fpu());
             jump(&end);
             bind(&notInt32);
             unboxDouble(src, dest.fpu());
             bind(&end);
         } else {
             if (src.payloadReg() != dest.gpr())
                 movl(src.payloadReg(), dest.gpr());
         }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5287,16 +5287,17 @@ JS::CompileOptions::CompileOptions(JSCon
     : principals(NULL),
       originPrincipals(NULL),
       version(cx->findVersion()),
       versionSet(false),
       utf8(false),
       filename(NULL),
       lineno(1),
       column(0),
+      element(NullPtr()),
       compileAndGo(cx->hasOption(JSOPTION_COMPILE_N_GO)),
       forEval(false),
       noScriptRval(cx->hasOption(JSOPTION_NO_SCRIPT_RVAL)),
       selfHostingMode(false),
       canLazilyParse(true),
       sourcePolicy(SAVE_SOURCE)
 {
 }
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3890,16 +3890,17 @@ struct JS_PUBLIC_API(CompileOptions) {
     JSPrincipals *principals;
     JSPrincipals *originPrincipals;
     JSVersion version;
     bool versionSet;
     bool utf8;
     const char *filename;
     unsigned lineno;
     unsigned column;
+    HandleObject element;
     bool compileAndGo;
     bool forEval;
     bool noScriptRval;
     bool selfHostingMode;
     bool canLazilyParse;
     enum SourcePolicy {
         NO_SOURCE,
         LAZY_SOURCE,
@@ -3910,16 +3911,17 @@ struct JS_PUBLIC_API(CompileOptions) {
     CompileOptions &setPrincipals(JSPrincipals *p) { principals = p; return *this; }
     CompileOptions &setOriginPrincipals(JSPrincipals *p) { originPrincipals = p; return *this; }
     CompileOptions &setVersion(JSVersion v) { version = v; versionSet = true; return *this; }
     CompileOptions &setUTF8(bool u) { utf8 = u; return *this; }
     CompileOptions &setFileAndLine(const char *f, unsigned l) {
         filename = f; lineno = l; return *this;
     }
     CompileOptions &setColumn(unsigned c) { column = c; return *this; }
+    CompileOptions &setElement(HandleObject e) { element = e; return *this; }
     CompileOptions &setCompileAndGo(bool cng) { compileAndGo = cng; return *this; }
     CompileOptions &setForEval(bool eval) { forEval = eval; return *this; }
     CompileOptions &setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
     CompileOptions &setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
     CompileOptions &setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; }
     CompileOptions &setSourcePolicy(SourcePolicy sp) { sourcePolicy = sp; return *this; }
 };
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1,10 +1,9 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * 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/. */
 
 /* JS shell. */
 
 #include <errno.h>
 #include <locale.h>
@@ -922,115 +921,121 @@ Evaluate(JSContext *cx, unsigned argc, j
         JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "evaluate");
         return false;
     }
 
     bool newContext = false;
     bool compileAndGo = true;
     bool noScriptRval = false;
     const char *fileName = "@evaluate";
+    RootedObject element(cx);
     JSAutoByteString fileNameBytes;
     RootedString sourceMapURL(cx);
     unsigned lineNumber = 1;
     RootedObject global(cx, NULL);
     bool catchTermination = false;
     bool saveFrameChain = false;
     RootedObject callerGlobal(cx, cx->global());
 
     global = JS_GetGlobalForObject(cx, &args.callee());
     if (!global)
         return false;
 
     if (args.length() == 2) {
-        RootedObject options(cx, &args[1].toObject());
+        RootedObject opts(cx, &args[1].toObject());
         RootedValue v(cx);
 
-        if (!JS_GetProperty(cx, options, "newContext", v.address()))
+        if (!JS_GetProperty(cx, opts, "newContext", v.address()))
             return false;
         if (!JSVAL_IS_VOID(v)) {
             JSBool b;
             if (!JS_ValueToBoolean(cx, v, &b))
                 return false;
             newContext = b;
         }
 
-        if (!JS_GetProperty(cx, options, "compileAndGo", v.address()))
+        if (!JS_GetProperty(cx, opts, "compileAndGo", v.address()))
             return false;
         if (!JSVAL_IS_VOID(v)) {
             JSBool b;
             if (!JS_ValueToBoolean(cx, v, &b))
                 return false;
             compileAndGo = b;
         }
 
-        if (!JS_GetProperty(cx, options, "noScriptRval", v.address()))
+        if (!JS_GetProperty(cx, opts, "noScriptRval", v.address()))
             return false;
         if (!JSVAL_IS_VOID(v)) {
             JSBool b;
             if (!JS_ValueToBoolean(cx, v, &b))
                 return false;
             noScriptRval = b;
         }
 
-        if (!JS_GetProperty(cx, options, "fileName", v.address()))
+        if (!JS_GetProperty(cx, opts, "fileName", v.address()))
             return false;
         if (JSVAL_IS_NULL(v)) {
             fileName = NULL;
         } else if (!JSVAL_IS_VOID(v)) {
             JSString *s = JS_ValueToString(cx, v);
             if (!s)
                 return false;
             fileName = fileNameBytes.encodeLatin1(cx, s);
             if (!fileName)
                 return false;
         }
 
-        if (!JS_GetProperty(cx, options, "sourceMapURL", v.address()))
+        if (!JS_GetProperty(cx, opts, "element", v.address()))
+            return false;
+        if (!JSVAL_IS_PRIMITIVE(v))
+            element = JSVAL_TO_OBJECT(v);
+
+        if (!JS_GetProperty(cx, opts, "sourceMapURL", v.address()))
             return false;
         if (!JSVAL_IS_VOID(v)) {
             sourceMapURL = JS_ValueToString(cx, v);
             if (!sourceMapURL)
                 return false;
         }
 
-        if (!JS_GetProperty(cx, options, "lineNumber", v.address()))
+        if (!JS_GetProperty(cx, opts, "lineNumber", v.address()))
             return false;
         if (!JSVAL_IS_VOID(v)) {
             uint32_t u;
             if (!JS_ValueToECMAUint32(cx, v, &u))
                 return false;
             lineNumber = u;
         }
 
-        if (!JS_GetProperty(cx, options, "global", v.address()))
+        if (!JS_GetProperty(cx, opts, "global", v.address()))
             return false;
         if (!JSVAL_IS_VOID(v)) {
             global = JSVAL_IS_PRIMITIVE(v) ? NULL : JSVAL_TO_OBJECT(v);
             if (global) {
                 global = js::UncheckedUnwrap(global);
                 if (!global)
                     return false;
             }
             if (!global || !(JS_GetClass(global)->flags & JSCLASS_IS_GLOBAL)) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
                                      "\"global\" passed to evaluate()", "not a global object");
                 return false;
             }
         }
 
-        if (!JS_GetProperty(cx, options, "catchTermination", v.address()))
+        if (!JS_GetProperty(cx, opts, "catchTermination", v.address()))
             return false;
         if (!JSVAL_IS_VOID(v)) {
             JSBool b;
             if (!JS_ValueToBoolean(cx, v, &b))
                 return false;
             catchTermination = b;
         }
 
-        if (!JS_GetProperty(cx, options, "saveFrameChain", v.address()))
+        if (!JS_GetProperty(cx, opts, "saveFrameChain", v.address()))
             return false;
         if (!JSVAL_IS_VOID(v)) {
             JSBool b;
             if (!JS_ValueToBoolean(cx, v, &b))
                 return false;
             saveFrameChain = b;
         }
     }
@@ -1050,26 +1055,29 @@ Evaluate(JSContext *cx, unsigned argc, j
     }
 
     AutoSaveFrameChain asfc(cx);
     if (saveFrameChain && !asfc.save())
         return false;
 
     {
         JSAutoCompartment ac(cx, global);
-        uint32_t saved = JS_GetOptions(cx);
-        uint32_t options = saved & ~(JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+        uint32_t oldopts = JS_GetOptions(cx);
+        uint32_t opts = oldopts & ~(JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
         if (compileAndGo)
-            options |= JSOPTION_COMPILE_N_GO;
+            opts |= JSOPTION_COMPILE_N_GO;
         if (noScriptRval)
-            options |= JSOPTION_NO_SCRIPT_RVAL;
-
-        JS_SetOptions(cx, options);
-        RootedScript script(cx, JS_CompileUCScript(cx, global, codeChars, codeLength, fileName, lineNumber));
-        JS_SetOptions(cx, saved);
+            opts |= JSOPTION_NO_SCRIPT_RVAL;
+
+        JS_SetOptions(cx, opts);
+        CompileOptions options(cx);
+        options.setFileAndLine(fileName, lineNumber);
+        options.setElement(element);
+        RootedScript script(cx, JS::Compile(cx, global, options, codeChars, codeLength));
+        JS_SetOptions(cx, oldopts);
         if (!script)
             return false;
 
         if (sourceMapURL && !script->scriptSource()->hasSourceMap()) {
             const jschar *smurl = JS_GetStringCharsZ(cx, sourceMapURL);
             if (!smurl)
                 return false;
             jschar *smurl_copy = js_strdup(cx, smurl);
--- a/js/src/tests/README.txt
+++ b/js/src/tests/README.txt
@@ -14,17 +14,18 @@ For general information, see
 https://developer.mozilla.org/en-US/docs/SpiderMonkey/Creating_JavaScript_tests
 
 Adding a test
 -------------
     Drop it in an appropriate directory under the tests directory.
 
         <fineprint> Some names are forbidden. Do not name your test browser.js,
         shell.js, jsref.js, template.js, user.js, js-test-driver-begin.js, or
-        js-test-driver-end.js. </fineprint>
+        js-test-driver-end.js, or any of the names of the files in supporting/.
+        </fineprint>
 
 Adjusting when and how a test runs
 ----------------------------------
     Put a comment at the top of the header matching the format:
         // |reftest| <failure-type> -- <comment>
 
     Where <failure-type> is a standard reftest <failure-type> string, as documented by:
         http://mxr.mozilla.org/mozilla-central/source/layout/tools/reftest/README.txt
--- a/js/src/tests/lib/manifest.py
+++ b/js/src/tests/lib/manifest.py
@@ -210,17 +210,17 @@ def _emit_manifest_at(location, relative
     for k, test_list in manifests.iteritems():
         fullpath = os.path.join(location, k)
         if os.path.isdir(fullpath):
             manifest.append("include " + k + "/jstests.list")
             relpath = os.path.join(relative, k)
             _emit_manifest_at(fullpath, relpath, test_list, depth + 1)
         else:
             numTestFiles += 1
-            assert(len(test_list) == 1)
+            assert len(test_list) == 1
             line = _build_manifest_script_entry(k, test_list[0])
             manifest.append(line)
 
     # Always present our manifest in sorted order.
     manifest.sort()
 
     # If we have tests, we have to set the url-prefix so reftest can find them.
     if numTestFiles > 0:
@@ -339,17 +339,18 @@ def load(location, xul_tester, reldir = 
     - an external manifest entry for a containing directory,
     - most commonly: the header of the test case itself.
     """
     # The list of tests that we are collecting.
     tests = []
 
     # Any file whose basename matches something in this set is ignored.
     EXCLUDED = set(('browser.js', 'shell.js', 'jsref.js', 'template.js',
-                    'user.js', 'js-test-driver-begin.js', 'js-test-driver-end.js'))
+                    'user.js', 'test402-browser.js', 'test402-shell.js',
+                    'js-test-driver-begin.js', 'js-test-driver-end.js'))
 
     manifestFile = os.path.join(location, 'jstests.list')
     externalManifestEntries = _parse_external_manifest(manifestFile, '')
 
     for root, basename in _find_all_js_files(location, location):
         # Skip js files in the root test directory.
         if not root:
             continue
new file mode 100644
--- /dev/null
+++ b/js/src/tests/supporting/README
@@ -0,0 +1,9 @@
+================================
+= DANGER!!!!!!!!1!!!cos(0)!!!! =
+================================
+
+Any *.js files you add in this directory *will* be considered to be tests by the
+test-staging Makefile target, used to package up JS tests for running on
+Tinderbox.  You are now probably sorry this is the case.  But there is a
+hackaround!  To make the packaging algorithm ignore a *.js file here, add it to
+the EXCLUDED set in lib/manifest.py.
new file mode 100644
--- /dev/null
+++ b/js/src/tests/supporting/test402-browser.js
@@ -0,0 +1,40 @@
+/* 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/. */
+
+/*
+ * Undo at least the damage done by taintArray so that the jstests
+ * harness won't die. The properties added to Object.prototype by the various
+ * tests have names that are less likely to cause trouble.
+ */
+setRestoreFunction((function () {
+    var Array_indexOf = Array.prototype.indexOf;
+    var Array_join = Array.prototype.join;
+    var Array_push = Array.prototype.push;
+    var Array_slice = Array.prototype.slice;
+    var Array_sort = Array.prototype.sort;
+    return function () {
+        delete Array.prototype["0"];
+        Array.prototype.indexOf = Array_indexOf;
+        Array.prototype.join = Array_join;
+        Array.prototype.push = Array_push;
+        Array.prototype.slice = Array_slice;
+        Array.prototype.sort = Array_sort;
+    };
+}()));
+
+/*
+ * Loading include files into the browser from a script so that they become
+ * synchronously available to that same script is difficult. Instead, request
+ * all of them to be loaded before we start.
+ */
+include("test402/lib/testBuiltInObject.js");
+include("test402/lib/testIntl.js");
+
+/*
+ * Test262 function $INCLUDE loads a file with support functions for the tests.
+ * Since we've already loaded all of these files, just ignore the call.
+ * This function replaces one in shell.js.
+ */
+function $INCLUDE(file) {
+}
new file mode 100644
--- /dev/null
+++ b/js/src/tests/supporting/test402-shell.js
@@ -0,0 +1,33 @@
+/* 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/. */
+
+/*
+ * Test402 tests pass unless they throw. Note that this isn't true for all
+ * Test262 test cases - for the ones marked @negative the logic is inverted.
+ */
+testPassesUnlessItThrows();
+
+/*
+ * Test262 function $ERROR throws an error with the message provided. Test262
+ * test cases call it to indicate failure.
+ */
+function $ERROR(msg) {
+    throw new Error("Test402 error: " + msg);
+}
+
+/*
+ * Test262 function $INCLUDE loads a file with support functions for the tests.
+ * This function is replaced in browser.js.
+ */
+function $INCLUDE(file) {
+    loadRelativeToScript("lib/" + file);
+}
+
+/*
+ * Test262 function fnGlobalObject returns the global object.
+ */
+var __globalObject = Function("return this;")();
+function fnGlobalObject() {
+     return __globalObject;
+}
--- a/js/src/tests/update-test402.sh
+++ b/js/src/tests/update-test402.sh
@@ -6,16 +6,19 @@
 # Updates the jstests copy of the test cases of Test402, the conformance test
 # suite for standard ECMA-402, ECMAScript Internationalization API
 # Specification.
 
 # Usage: update-test402.sh <URL of test262 hg>
 # E.g.: update-test402.sh http://hg.ecmascript.org/tests/test262/
 # Note that test402 is part of the test262 repository.
 
+# Abort when an error occurs.
+set -e
+
 if [ $# -lt 1 ]; then
   echo "Usage: update-test402.sh <URL of test262 hg>"
   exit 1
 fi
 
 # Test402 in its original form uses the harness of Test262, the conformance
 # test suite for standard ECMA-262, ECMAScript Language Specification, and its
 # test cases are part of the test262 repository.
@@ -42,20 +45,25 @@ cp ${tmp_dir}/LICENSE ${test402_dir}
 # Create empty browser.js and shell.js in each test directory to keep
 # jstests happy.
 for dir in `find test402/ch* -type d -print` ; do
     touch $dir/browser.js
     touch $dir/shell.js
 done
 
 # Restore our own jstests adapter files.
-hg revert --no-backup test402/browser.js
-hg revert --no-backup test402/shell.js
+cp supporting/test402-browser.js test402/browser.js
+cp supporting/test402-shell.js test402/shell.js
 
 # Keep a record of what we imported.
 echo "URL:         $1" > ${test402_dir}/HG-INFO
 hg -R ${tmp_dir} log -r. >> ${test402_dir}/HG-INFO
 
 # Update for the patch.
 hg addremove ${test402_dir}
 
 # Get rid of the Test262 clone.
 rm -rf ${tmp_dir}
+
+# The alert reader may now be wondering: what about test402 tests we don't
+# currently pass?  We disable such tests in js/src/tests/jstests.list, one by
+# one.  This has the moderate benefit that if a bug is fixed, only that one file
+# must be updated, and we don't have to rerun this script.
--- a/js/xpconnect/idl/nsIXPConnect.idl
+++ b/js/xpconnect/idl/nsIXPConnect.idl
@@ -65,28 +65,27 @@ class nsScriptObjectTracer;
 
 /***************************************************************************/
 [uuid(909e8641-7c54-4dff-9b94-ba631f057b33)]
 interface nsIXPConnectJSObjectHolder : nsISupports
 {
     [notxpcom, nostdcall] JSObjectPtr GetJSObject();
 };
 
-[uuid(b1b0d624-0759-4037-9517-45972781dcc1)]
+[uuid(2d08015d-7556-4f12-9e89-4c756d129310)]
 interface nsIXPConnectWrappedNative : nsIXPConnectJSObjectHolder
 {
     /* attribute 'JSObject' inherited from nsIXPConnectJSObjectHolder */
     readonly attribute nsISupports      Native;
     readonly attribute JSObjectPtr      JSObjectPrototype;
 
     /**
      * These are here as an aid to nsIXPCScriptable implementors
      */
 
-    readonly attribute nsIXPConnect XPConnect;
     nsIInterfaceInfo FindInterfaceWithMember(in JSHandleId nameID);
     nsIInterfaceInfo FindInterfaceWithName(in JSHandleId nameID);
     [notxpcom] bool HasNativeMember(in JSHandleId name);
 
     void debugDump(in short depth);
 
     /*
      * This finishes initializing a wrapped global, doing the parts that we
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -257,22 +257,17 @@ File(JSContext *cx, unsigned argc, Value
     NS_ASSERTION(initializer, "what?");
 
     rv = initializer->Initialize(nullptr, cx, nullptr, args);
     if (NS_FAILED(rv)) {
         XPCThrower::Throw(rv, cx);
         return false;
     }
 
-    nsXPConnect* xpc = nsXPConnect::GetXPConnect();
-    if (!xpc) {
-        XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx);
-        return false;
-    }
-
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     JSObject* glob = JS_GetGlobalForScopeChain(cx);
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     rv = xpc->WrapNativeToJSVal(cx, glob, native, nullptr,
                                 &NS_GET_IID(nsISupports),
                                 true, args.rval().address(), nullptr);
     if (NS_FAILED(rv)) {
         XPCThrower::Throw(rv, cx);
@@ -297,22 +292,17 @@ Blob(JSContext *cx, unsigned argc, Value
     NS_ASSERTION(initializer, "what?");
 
     rv = initializer->Initialize(nullptr, cx, nullptr, args);
     if (NS_FAILED(rv)) {
         XPCThrower::Throw(rv, cx);
         return false;
     }
 
-    nsXPConnect* xpc = nsXPConnect::GetXPConnect();
-    if (!xpc) {
-        XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx);
-        return false;
-    }
-
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     JSObject* glob = JS_GetGlobalForScopeChain(cx);
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     rv = xpc->WrapNativeToJSVal(cx, glob, native, nullptr,
                                 &NS_GET_IID(nsISupports),
                                 true, args.rval().address(), nullptr);
     if (NS_FAILED(rv)) {
         XPCThrower::Throw(rv, cx);
--- a/js/xpconnect/src/XPCCallContext.cpp
+++ b/js/xpconnect/src/XPCCallContext.cpp
@@ -19,17 +19,17 @@ XPCCallContext::XPCCallContext(XPCContex
                                JSContext* cx       /* = GetDefaultJSContext() */,
                                HandleObject obj    /* = nullptr               */,
                                HandleObject funobj /* = nullptr               */,
                                HandleId name       /* = JSID_VOID             */,
                                unsigned argc       /* = NO_ARGS               */,
                                jsval *argv         /* = nullptr               */,
                                jsval *rval         /* = nullptr               */)
     :   mState(INIT_FAILED),
-        mXPC(nsXPConnect::GetXPConnect()),
+        mXPC(nsXPConnect::XPConnect()),
         mXPCContext(nullptr),
         mJSContext(cx),
         mContextPopRequired(false),
         mDestroyJSContextInDestructor(false),
         mCallerLanguage(callerLanguage),
         mFlattenedJSObject(cx),
         mWrapper(nullptr),
         mTearOff(nullptr),
@@ -43,17 +43,17 @@ XPCCallContext::XPCCallContext(XPCContex
 XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
                                JSContext* cx,
                                JSBool callBeginRequest,
                                HandleObject obj,
                                HandleObject flattenedJSObject,
                                XPCWrappedNative* wrapper,
                                XPCWrappedNativeTearOff* tearOff)
     :   mState(INIT_FAILED),
-        mXPC(nsXPConnect::GetXPConnect()),
+        mXPC(nsXPConnect::XPConnect()),
         mXPCContext(nullptr),
         mJSContext(cx),
         mContextPopRequired(false),
         mDestroyJSContextInDestructor(false),
         mCallerLanguage(callerLanguage),
         mFlattenedJSObject(cx, flattenedJSObject),
         mWrapper(wrapper),
         mTearOff(tearOff),
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -60,20 +60,17 @@ JSValIsInterfaceOfType(JSContext *cx, Ha
 
     nsCOMPtr<nsIXPConnectWrappedNative> wn;
     nsCOMPtr<nsISupports> sup;
     nsISupports* iface;
 
     if (v.isPrimitive())
         return false;
 
-    nsCOMPtr<nsIXPConnect> xpc = nsXPConnect::GetXPConnect();
-    if (!xpc)
-        return false;
-
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     RootedObject obj(cx, &v.toObject());
     if (NS_SUCCEEDED(xpc->GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wn))) && wn &&
         NS_SUCCEEDED(wn->Native()->QueryInterface(iid, (void**)&iface)) && iface)
     {
         NS_RELEASE(iface);
         return true;
     }
     return false;
@@ -320,36 +317,33 @@ nsXPCComponents_Interfaces::NewResolve(n
             GetInfoForName(name.ptr(), getter_AddRefs(info));
         if (!info)
             return NS_OK;
 
         nsCOMPtr<nsIJSIID> nsid =
             dont_AddRef(static_cast<nsIJSIID*>(nsJSIID::NewID(info)));
 
         if (nsid) {
-            nsCOMPtr<nsIXPConnect> xpc;
-            wrapper->GetXPConnect(getter_AddRefs(xpc));
-            if (xpc) {
-                nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-                if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
-                                                 static_cast<nsIJSIID*>(nsid),
-                                                 NS_GET_IID(nsIJSIID),
-                                                 getter_AddRefs(holder)))) {
-                    RootedObject idobj(cx);
-                    if (holder &&
-                        // Assign, not compare
-                        (idobj = holder->GetJSObject())) {
-                        *objp = obj;
-                        *_retval = JS_DefinePropertyById(cx, obj, id,
-                                                         OBJECT_TO_JSVAL(idobj),
-                                                         nullptr, nullptr,
-                                                         JSPROP_ENUMERATE |
-                                                         JSPROP_READONLY |
-                                                         JSPROP_PERMANENT);
-                    }
+            nsXPConnect* xpc = nsXPConnect::XPConnect();
+            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+            if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
+                                             static_cast<nsIJSIID*>(nsid),
+                                             NS_GET_IID(nsIJSIID),
+                                             getter_AddRefs(holder)))) {
+                RootedObject idobj(cx);
+                if (holder &&
+                    // Assign, not compare
+                    (idobj = holder->GetJSObject())) {
+                    *objp = obj;
+                    *_retval = JS_DefinePropertyById(cx, obj, id,
+                                                     OBJECT_TO_JSVAL(idobj),
+                                                     nullptr, nullptr,
+                                                     JSPROP_ENUMERATE |
+                                                     JSPROP_READONLY |
+                                                     JSPROP_PERMANENT);
                 }
             }
         }
     }
     return NS_OK;
 }
 
 /* string canCreateWrapper (in nsIIDPtr iid); */
@@ -616,37 +610,34 @@ nsXPCComponents_InterfacesByID::NewResol
             return NS_OK;
 
         nsCOMPtr<nsIJSIID> nsid =
             dont_AddRef(static_cast<nsIJSIID*>(nsJSIID::NewID(info)));
 
         if (!nsid)
             return NS_ERROR_OUT_OF_MEMORY;
 
-        nsCOMPtr<nsIXPConnect> xpc;
-        wrapper->GetXPConnect(getter_AddRefs(xpc));
-        if (xpc) {
-            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-            if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
-                                             static_cast<nsIJSIID*>(nsid),
-                                             NS_GET_IID(nsIJSIID),
-                                             getter_AddRefs(holder)))) {
-                RootedObject idobj(cx);
-                if (holder &&
-                    // Assign, not compare
-                    (idobj = holder->GetJSObject())) {
-                    *objp = obj;
-                    *_retval =
-                        JS_DefinePropertyById(cx, obj, id,
-                                              OBJECT_TO_JSVAL(idobj),
-                                              nullptr, nullptr,
-                                              JSPROP_ENUMERATE |
-                                              JSPROP_READONLY |
-                                              JSPROP_PERMANENT);
-                }
+        nsXPConnect* xpc = nsXPConnect::XPConnect();
+        nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+        if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
+                                         static_cast<nsIJSIID*>(nsid),
+                                            NS_GET_IID(nsIJSIID),
+                                            getter_AddRefs(holder)))) {
+            RootedObject idobj(cx);
+            if (holder &&
+                // Assign, not compare
+                (idobj = holder->GetJSObject())) {
+                *objp = obj;
+                *_retval =
+                    JS_DefinePropertyById(cx, obj, id,
+                                          OBJECT_TO_JSVAL(idobj),
+                                          nullptr, nullptr,
+                                          JSPROP_ENUMERATE |
+                                          JSPROP_READONLY |
+                                          JSPROP_PERMANENT);
             }
         }
     }
     return NS_OK;
 }
 
 /* string canCreateWrapper (in nsIIDPtr iid); */
 NS_IMETHODIMP
@@ -898,36 +889,33 @@ nsXPCComponents_Classes::NewResolve(nsIX
 
     JSAutoByteString name;
     if (JSID_IS_STRING(id) &&
         name.encodeLatin1(cx, JSID_TO_STRING(id)) &&
         name.ptr()[0] != '{') { // we only allow contractids here
         nsCOMPtr<nsIJSCID> nsid =
             dont_AddRef(static_cast<nsIJSCID*>(nsJSCID::NewID(name.ptr())));
         if (nsid) {
-            nsCOMPtr<nsIXPConnect> xpc;
-            wrapper->GetXPConnect(getter_AddRefs(xpc));
-            if (xpc) {
-                nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-                if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
-                                                 static_cast<nsIJSCID*>(nsid),
-                                                 NS_GET_IID(nsIJSCID),
-                                                 getter_AddRefs(holder)))) {
-                    RootedObject idobj(cx);
-                    if (holder &&
-                        // Assign, not compare
+            nsXPConnect* xpc = nsXPConnect::XPConnect();
+            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+            if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
+                                             static_cast<nsIJSCID*>(nsid),
+                                             NS_GET_IID(nsIJSCID),
+                                             getter_AddRefs(holder)))) {
+                RootedObject idobj(cx);
+                if (holder &&
+                    // Assign, not compare
                         (idobj = holder->GetJSObject())) {
-                        *objp = obj;
-                        *_retval = JS_DefinePropertyById(cx, obj, id,
-                                                         OBJECT_TO_JSVAL(idobj),
-                                                         nullptr, nullptr,
-                                                         JSPROP_ENUMERATE |
-                                                         JSPROP_READONLY |
-                                                         JSPROP_PERMANENT);
-                    }
+                    *objp = obj;
+                    *_retval = JS_DefinePropertyById(cx, obj, id,
+                                                     OBJECT_TO_JSVAL(idobj),
+                                                     nullptr, nullptr,
+                                                     JSPROP_ENUMERATE |
+                                                     JSPROP_READONLY |
+                                                     JSPROP_PERMANENT);
                 }
             }
         }
     }
     return NS_OK;
 }
 
 /***************************************************************************/
@@ -1162,36 +1150,33 @@ nsXPCComponents_ClassesByID::NewResolve(
     JSAutoByteString name;
     RootedString str(cx, JSID_TO_STRING(id));
     if (name.encodeLatin1(cx, str) && name.ptr()[0] == '{' &&
         IsRegisteredCLSID(name.ptr())) // we only allow canonical CLSIDs here
     {
         nsCOMPtr<nsIJSCID> nsid =
             dont_AddRef(static_cast<nsIJSCID*>(nsJSCID::NewID(name.ptr())));
         if (nsid) {
-            nsCOMPtr<nsIXPConnect> xpc;
-            wrapper->GetXPConnect(getter_AddRefs(xpc));
-            if (xpc) {
-                nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-                if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
-                                                 static_cast<nsIJSCID*>(nsid),
-                                                 NS_GET_IID(nsIJSCID),
-                                                 getter_AddRefs(holder)))) {
-                    RootedObject idobj(cx);
-                    if (holder &&
-                        // Assign, not compare
-                        (idobj = holder->GetJSObject())) {
-                        *objp = obj;
-                        *_retval = JS_DefinePropertyById(cx, obj, id,
-                                                         ObjectValue(*idobj),
-                                                         nullptr, nullptr,
-                                                         JSPROP_ENUMERATE |
-                                                         JSPROP_READONLY |
-                                                         JSPROP_PERMANENT);
-                    }
+            nsXPConnect* xpc = nsXPConnect::XPConnect();
+            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+            if (NS_SUCCEEDED(xpc->WrapNative(cx, obj,
+                                             static_cast<nsIJSCID*>(nsid),
+                                             NS_GET_IID(nsIJSCID),
+                                             getter_AddRefs(holder)))) {
+                RootedObject idobj(cx);
+                if (holder &&
+                    // Assign, not compare
+                    (idobj = holder->GetJSObject())) {
+                    *objp = obj;
+                    *_retval = JS_DefinePropertyById(cx, obj, id,
+                                                     ObjectValue(*idobj),
+                                                     nullptr, nullptr,
+                                                     JSPROP_ENUMERATE |
+                                                     JSPROP_READONLY |
+                                                     JSPROP_PERMANENT);
                 }
             }
         }
     }
     return NS_OK;
 }
 
 
@@ -1958,17 +1943,17 @@ nsresult
 nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
                                            JSContext *cx, HandleObject obj,
                                            const CallArgs &args, bool *_retval)
 {
     XPCCallContext ccx(JS_CALLER, cx);
     if (!ccx.IsValid())
         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
 
-    nsXPConnect* xpc = ccx.GetXPConnect();
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     XPCContext* xpcc = ccx.GetXPCContext();
 
     // Do the security check if necessary
 
     nsIXPCSecurityManager* sm =
             xpcc->GetAppropriateSecurityManager(nsIXPCSecurityManager::HOOK_CREATE_INSTANCE);
     if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsXPCException::GetCID()))) {
         // the security manager vetoed. It should have set an exception.
@@ -2233,17 +2218,17 @@ nsXPCConstructor::Construct(nsIXPConnect
 nsresult
 nsXPCConstructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,JSContext *cx,
                                   HandleObject obj, const CallArgs &args, bool *_retval)
 {
     XPCCallContext ccx(JS_CALLER, cx);
     if (!ccx.IsValid())
         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
 
-    nsXPConnect* xpc = ccx.GetXPConnect();
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
 
     // security check not required because we are going to call through the
     // code which is reflected into JS which will do that for us later.
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> cidHolder;
     nsCOMPtr<nsIXPConnectJSObjectHolder> iidHolder;
     RootedObject cidObj(cx);
     RootedObject iidObj(cx);
@@ -2467,17 +2452,17 @@ nsXPCComponents_Constructor::CallOrConst
         return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
 
     // get the various other object pointers we need
 
     XPCCallContext ccx(JS_CALLER, cx);
     if (!ccx.IsValid())
         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
 
-    nsXPConnect* xpc = ccx.GetXPConnect();
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     XPCContext* xpcc = ccx.GetXPCContext();
     XPCWrappedNativeScope* scope = GetObjectScope(obj);
     nsXPCComponents* comp;
 
     if (!xpc || !xpcc || !scope || !(comp = scope->GetComponents()))
         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
 
     // Do the security check if necessary
@@ -2803,19 +2788,18 @@ nsXPCComponents_Utils::ReportError(const
     }
 
     // It's not a JS Error object, so we synthesize as best we're able.
     RootedString msgstr(cx, JS_ValueToString(cx, error));
     if (!msgstr)
         return NS_OK;
 
     nsCOMPtr<nsIStackFrame> frame;
-    nsXPConnect *xpc = nsXPConnect::GetXPConnect();
-    if (xpc)
-        xpc->GetCurrentJSStack(getter_AddRefs(frame));
+    nsXPConnect *xpc = nsXPConnect::XPConnect();
+    xpc->GetCurrentJSStack(getter_AddRefs(frame));
 
     nsXPIDLCString fileName;
     int32_t lineNo = 0;
     if (frame) {
         frame->GetFilename(getter_Copies(fileName));
         frame->GetLineNumber(&lineNo);
     }
 
@@ -3477,19 +3461,17 @@ GetPrincipalFromString(JSContext *cx, Ha
 // for sandbox constructor  the first argument can be a principal object or
 // a script object principal (Document, Window)
 nsresult
 GetPrincipalOrSOP(JSContext *cx, HandleObject from, nsISupports **out)
 {
     MOZ_ASSERT(out);
     *out = NULL;
 
-    nsCOMPtr<nsIXPConnect> xpc = nsXPConnect::GetXPConnect();
-    if (!xpc)
-        return NS_ERROR_XPC_UNEXPECTED;
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
     xpc->GetWrappedNativeOfJSObject(cx, from,
                                     getter_AddRefs(wrapper));
 
     NS_ENSURE_TRUE(wrapper, NS_ERROR_INVALID_ARG);
 
     if (nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryWrappedNative(wrapper)) {
         sop.forget(out);
@@ -3680,19 +3662,17 @@ ParseOptionsObject(JSContext *cx, jsval 
 
 static nsresult
 AssembleSandboxMemoryReporterName(JSContext *cx, nsCString &sandboxName)
 {
     // Use a default name when the caller did not provide a sandboxName.
     if (sandboxName.IsEmpty())
         sandboxName = NS_LITERAL_CSTRING("[anonymous sandbox]");
 
-    nsXPConnect* xpc = nsXPConnect::GetXPConnect();
-    NS_ENSURE_TRUE(xpc, NS_ERROR_XPC_UNEXPECTED);
-
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     // Get the xpconnect native call context.
     nsAXPCNativeCallContext *cc = nullptr;
     xpc->GetCurrentNativeCallContext(&cc);
     NS_ENSURE_TRUE(cc, NS_ERROR_INVALID_ARG);
 
     // Get the current source info from xpc.
     nsCOMPtr<nsIStackFrame> frame;
     xpc->GetCurrentJSStack(getter_AddRefs(frame));
@@ -4419,19 +4399,19 @@ nsXPCComponents_Utils::Dispatch(const js
             return NS_ERROR_FAILURE;
     }
 
     // Get an XPCWrappedJS for |runnable|.
     if (!runnable.isObject())
         return NS_ERROR_INVALID_ARG;
 
     nsCOMPtr<nsIRunnable> run;
-    nsresult rv = nsXPConnect::GetXPConnect()->WrapJS(cx, &runnable.toObject(),
-                                                      NS_GET_IID(nsIRunnable),
-                                                      getter_AddRefs(run));
+    nsresult rv = nsXPConnect::XPConnect()->WrapJS(cx, &runnable.toObject(),
+                                                   NS_GET_IID(nsIRunnable),
+                                                   getter_AddRefs(run));
     NS_ENSURE_SUCCESS(rv, rv);
     MOZ_ASSERT(run);
 
     // Dispatch.
     return NS_DispatchToMainThread(run);
 }
 
 /* string canCreateWrapper (in nsIIDPtr iid); */
@@ -4764,19 +4744,17 @@ nsXPCComponents::IsSuccessCode(nsresult 
     *out = NS_SUCCEEDED(result);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXPCComponents::GetStack(nsIStackFrame * *aStack)
 {
     nsresult rv;
-    nsXPConnect* xpc = nsXPConnect::GetXPConnect();
-    if (!xpc)
-        return NS_ERROR_FAILURE;
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     rv = xpc->GetCurrentJSStack(aStack);
     return rv;
 }
 
 NS_IMETHODIMP
 nsXPCComponents::GetManager(nsIComponentManager * *aManager)
 {
     NS_ASSERTION(aManager, "bad param");
--- a/js/xpconnect/src/XPCException.cpp
+++ b/js/xpconnect/src/XPCException.cpp
@@ -292,19 +292,17 @@ nsXPCException::Initialize(const char *a
         // Later we may allow other locations?
         nsresult rc;
         if (NS_FAILED(rc = aLocation->GetFilename(&mFilename)))
             return rc;
         if (NS_FAILED(rc = aLocation->GetLineNumber(&mLineNumber)))
             return rc;
     } else {
         nsresult rv;
-        nsXPConnect* xpc = nsXPConnect::GetXPConnect();
-        if (!xpc)
-            return NS_ERROR_FAILURE;
+        nsXPConnect* xpc = nsXPConnect::XPConnect();
         rv = xpc->GetCurrentJSStack(&mLocation);
         if (NS_FAILED(rv))
             return rv;
     }
 
     if (aData) {
         mData = aData;
         NS_ADDREF(mData);
@@ -395,21 +393,17 @@ nsXPCException::NewException(const char 
     if (e) {
         NS_ADDREF(e);
 
         nsIStackFrame* location;
         if (aLocation) {
             location = aLocation;
             NS_ADDREF(location);
         } else {
-            nsXPConnect* xpc = nsXPConnect::GetXPConnect();
-            if (!xpc) {
-                NS_RELEASE(e);
-                return NS_ERROR_FAILURE;
-            }
+            nsXPConnect* xpc = nsXPConnect::XPConnect();
             rv = xpc->GetCurrentJSStack(&location);
             if (NS_FAILED(rv)) {
                 NS_RELEASE(e);
                 return NS_ERROR_FAILURE;
             }
             // it is legal for there to be no active JS stack, if C++ code
             // is operating on a JS-implemented interface pointer without
             // having been called in turn by JS.  This happens in the JS
--- a/js/xpconnect/src/XPCInlines.h
+++ b/js/xpconnect/src/XPCInlines.h
@@ -35,23 +35,16 @@ XPCJSRuntime::AddObjectHolderRoot(XPCJSO
 /***************************************************************************/
 
 inline JSBool
 XPCCallContext::IsValid() const
 {
     return mState != INIT_FAILED;
 }
 
-inline nsXPConnect*
-XPCCallContext::GetXPConnect() const
-{
-    CHECK_STATE(HAVE_CONTEXT);
-    return mXPC;
-}
-
 inline XPCJSRuntime*
 XPCCallContext::GetRuntime() const
 {
     CHECK_STATE(HAVE_CONTEXT);
     return mXPCContext->GetRuntime();
 }
 
 inline XPCContext*
@@ -580,17 +573,17 @@ xpc_ForcePropertyResolve(JSContext* cx, 
     if (!JS_LookupPropertyById(cx, obj, id, &prop))
         return false;
     return true;
 }
 
 inline jsid
 GetRTIdByIndex(JSContext *cx, unsigned index)
 {
-  XPCJSRuntime *rt = nsXPConnect::FastGetXPConnect()->GetRuntime();
+  XPCJSRuntime *rt = nsXPConnect::XPConnect()->GetRuntime();
   return rt->GetStringID(index);
 }
 
 inline
 JSBool ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx)
 {
     XPCThrower::ThrowBadParam(rv, paramNum, ccx);
     return false;
--- a/js/xpconnect/src/XPCJSContextStack.cpp
+++ b/js/xpconnect/src/XPCJSContextStack.cpp
@@ -142,20 +142,17 @@ XPCJSContextStack::GetSafeJSContext()
 
     // Start by getting the principal holder and principal for this
     // context.  If we can't manage that, don't bother with the rest.
     nsRefPtr<nsNullPrincipal> principal = new nsNullPrincipal();
     nsresult rv = principal->Init();
     if (NS_FAILED(rv))
         return NULL;
 
-    nsRefPtr<nsXPConnect> xpc = nsXPConnect::GetXPConnect();
-    if (!xpc)
-        return NULL;
-
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     XPCJSRuntime* xpcrt = xpc->GetRuntime();
     if (!xpcrt)
         return NULL;
 
     JSRuntime *rt = xpcrt->GetJSRuntime();
     if (!rt)
         return NULL;
 
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -710,20 +710,17 @@ GetIIDArg(uint32_t argc, const JS::Value
 
     return iid;
 }
 
 static void
 GetWrapperObject(MutableHandleObject obj)
 {
     obj.set(NULL);
-    nsXPConnect* xpc = nsXPConnect::GetXPConnect();
-    if (!xpc)
-        return;
-
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     nsAXPCNativeCallContext *ccxp = NULL;
     xpc->GetCurrentNativeCallContext(&ccxp);
     if (!ccxp)
         return;
 
     nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
     ccxp->GetCalleeWrapper(getter_AddRefs(wrapper));
     obj.set(wrapper->GetJSObject());
@@ -765,17 +762,17 @@ nsJSCID::CreateInstance(const JS::Value&
 
     nsCOMPtr<nsISupports> inst;
     rv = compMgr->CreateInstance(mDetails.ID(), nullptr, *iid, getter_AddRefs(inst));
     NS_ASSERTION(NS_FAILED(rv) || inst, "component manager returned success, but instance is null!");
 
     if (NS_FAILED(rv) || !inst)
         return NS_ERROR_XPC_CI_RETURNED_FAILURE;
 
-    rv = nsXPConnect::GetXPConnect()->WrapNativeToJSVal(cx, obj, inst, nullptr, iid, true, retval, nullptr);
+    rv = nsXPConnect::XPConnect()->WrapNativeToJSVal(cx, obj, inst, nullptr, iid, true, retval, nullptr);
     if (NS_FAILED(rv) || JSVAL_IS_PRIMITIVE(*retval))
         return NS_ERROR_XPC_CANT_CREATE_WN;
     return NS_OK;
 }
 
 /* nsISupports getService (); */
 NS_IMETHODIMP
 nsJSCID::GetService(const JS::Value& iidval, JSContext* cx,
@@ -814,17 +811,17 @@ nsJSCID::GetService(const JS::Value& iid
     nsCOMPtr<nsISupports> srvc;
     rv = svcMgr->GetService(mDetails.ID(), *iid, getter_AddRefs(srvc));
     NS_ASSERTION(NS_FAILED(rv) || srvc, "service manager returned success, but service is null!");
     if (NS_FAILED(rv) || !srvc)
         return NS_ERROR_XPC_GS_RETURNED_FAILURE;
 
     RootedObject instJSObj(cx);
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-    rv = nsXPConnect::GetXPConnect()->WrapNative(cx, obj, srvc, *iid, getter_AddRefs(holder));
+    rv = nsXPConnect::XPConnect()->WrapNative(cx, obj, srvc, *iid, getter_AddRefs(holder));
     if (NS_FAILED(rv) || !holder ||
         // Assign, not compare
         !(instJSObj = holder->GetJSObject()))
         return NS_ERROR_XPC_CANT_CREATE_WN;
 
     *retval = OBJECT_TO_JSVAL(instJSObj);
     return NS_OK;
 }
@@ -891,17 +888,17 @@ nsJSCID::HasInstance(nsIXPConnectWrapped
 JSObject *
 xpc_NewIDObject(JSContext *cx, HandleObject jsobj, const nsID& aID)
 {
     RootedObject obj(cx);
 
     nsCOMPtr<nsIJSID> iid =
             dont_AddRef(static_cast<nsIJSID*>(nsJSID::NewID(aID)));
     if (iid) {
-        nsXPConnect* xpc = nsXPConnect::GetXPConnect();
+        nsXPConnect* xpc = nsXPConnect::XPConnect();
         if (xpc) {
             nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
             nsresult rv = xpc->WrapNative(cx, jsobj,
                                           static_cast<nsISupports*>(iid),
                                           NS_GET_IID(nsIJSID),
                                           getter_AddRefs(holder));
             if (NS_SUCCEEDED(rv) && holder) {
                 obj = holder->GetJSObject();
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -377,34 +377,34 @@ XPCJSRuntime::TestJSHolder(void* aHolder
 
 // static
 void XPCJSRuntime::TraceBlackJS(JSTracer* trc, void* data)
 {
     XPCJSRuntime* self = (XPCJSRuntime*)data;
 
     // Skip this part if XPConnect is shutting down. We get into
     // bad locking problems with the thread iteration otherwise.
-    if (!self->GetXPConnect()->IsShuttingDown()) {
+    if (!nsXPConnect::XPConnect()->IsShuttingDown()) {
         // Trace those AutoMarkingPtr lists!
         if (AutoMarkingPtr *roots = Get()->mAutoRoots)
             roots->TraceJSAll(trc);
     }
 
     {
         XPCAutoLock lock(self->mMapLock);
 
         // XPCJSObjectHolders don't participate in cycle collection, so always
         // trace them here.
         XPCRootSetElem *e;
         for (e = self->mObjectHolderRoots; e; e = e->GetNextRoot())
             static_cast<XPCJSObjectHolder*>(e)->TraceJS(trc);
     }
 
     dom::TraceBlackJS(trc, JS_GetGCParameter(self->GetJSRuntime(), JSGC_NUMBER),
-                      self->GetXPConnect()->IsShuttingDown());
+                      nsXPConnect::XPConnect()->IsShuttingDown());
 }
 
 // static
 void XPCJSRuntime::TraceGrayJS(JSTracer* trc, void* data)
 {
     XPCJSRuntime* self = (XPCJSRuntime*)data;
 
     // Mark these roots as gray so the CC can walk them later.
@@ -603,19 +603,18 @@ XPCJSRuntime::UnmarkSkippableJSHolders()
 {
     XPCAutoLock lock(mMapLock);
     mJSHolders.Enumerate(UnmarkJSHolder, nullptr);
 }
 
 void
 xpc_UnmarkSkippableJSHolders()
 {
-    if (nsXPConnect::GetXPConnect() &&
-        nsXPConnect::GetXPConnect()->GetRuntime()) {
-        nsXPConnect::GetXPConnect()->GetRuntime()->UnmarkSkippableJSHolders();
+    if (nsXPConnect::XPConnect()->GetRuntime()) {
+        nsXPConnect::XPConnect()->GetRuntime()->UnmarkSkippableJSHolders();
     }
 }
 
 template<class T> static void
 DoDeferredRelease(nsTArray<T> &array)
 {
     while (1) {
         uint32_t count = array.Length();
@@ -931,17 +930,17 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp 
             // chance that a wrapper's set will change *while* a call is
             // happening which uses that wrapper's old interfface set. So,
             // we need to do this marking to avoid collecting those sets
             // that might no longer be otherwise reachable from the wrappers
             // or the wrapperprotos.
 
             // Skip this part if XPConnect is shutting down. We get into
             // bad locking problems with the thread iteration otherwise.
-            if (!self->GetXPConnect()->IsShuttingDown()) {
+            if (!nsXPConnect::XPConnect()->IsShuttingDown()) {
 
                 // Mark those AutoMarkingPtr lists!
                 if (AutoMarkingPtr *roots = Get()->mAutoRoots)
                     roots->MarkAfterJSFinalizeAll();
 
                 XPCCallContext* ccxp = XPCJSRuntime::Get()->GetCallContext();
                 while (ccxp) {
                     // Deal with the strictness of callcontext that
@@ -973,17 +972,17 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp 
             // kept separate, we could sweep only the ones belonging to
             // compartments being collected. Currently, though, NativeInterfaces
             // are shared between compartments. This ought to be fixed.
             void *sweepArg = isCompartmentGC ? UNMARK_ONLY : UNMARK_AND_SWEEP;
 
             // We don't want to sweep the JSClasses at shutdown time.
             // At this point there may be JSObjects using them that have
             // been removed from the other maps.
-            if (!self->GetXPConnect()->IsShuttingDown()) {
+            if (!nsXPConnect::XPConnect()->IsShuttingDown()) {
                 self->mNativeScriptableSharedMap->
                     Enumerate(JSClassSweeper, sweepArg);
             }
 
             if (!isCompartmentGC) {
                 self->mClassInfo2NativeSetMap->
                     Enumerate(NativeUnMarkedSetRemover, nullptr);
             }
@@ -1019,17 +1018,17 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp 
             // This allows us to perhaps minimize the growth of the
             // tearoffs. And also makes us not hold references to interfaces
             // on our wrapped natives that we are not actually using.
             //
             // XXX We may decide to not do this on *every* gc cycle.
 
             // Skip this part if XPConnect is shutting down. We get into
             // bad locking problems with the thread iteration otherwise.
-            if (!self->GetXPConnect()->IsShuttingDown()) {
+            if (!nsXPConnect::XPConnect()->IsShuttingDown()) {
                 // Do the marking...
 
                 XPCCallContext* ccxp = XPCJSRuntime::Get()->GetCallContext();
                 while (ccxp) {
                     // Deal with the strictness of callcontext that
                     // complains if you ask for a tearoff when
                     // it is in a state where the tearoff could not
                     // possibly be valid.
@@ -2254,17 +2253,17 @@ class XPCJSRuntimeStats : public JS::Run
 
 
         for (size_t i = 0; i != zoneStatsVector.length(); ++i)
             delete static_cast<xpc::ZoneStatsExtras*>(zoneStatsVector[i].extra);
     }
 
     virtual void initExtraZoneStats(JS::Zone *zone, JS::ZoneStats *zStats) MOZ_OVERRIDE {
         // Get the compartment's global.
-        nsXPConnect *xpc = nsXPConnect::GetXPConnect();
+        nsXPConnect *xpc = nsXPConnect::XPConnect();
         AutoSafeJSContext cx;
         JSCompartment *comp = js::GetAnyCompartmentInZone(zone);
         xpc::ZoneStatsExtras *extras = new xpc::ZoneStatsExtras;
         extras->pathPrefix.AssignLiteral("explicit/js-non-window/zones/");
         RootedObject global(cx, JS_GetGlobalForCompartmentOrNull(cx, comp));
         if (global) {
             // Need to enter the compartment, otherwise GetNativeOfWrapper()
             // might crash.
@@ -2287,17 +2286,17 @@ class XPCJSRuntimeStats : public JS::Run
     virtual void initExtraCompartmentStats(JSCompartment *c,
                                            JS::CompartmentStats *cstats) MOZ_OVERRIDE
     {
         xpc::CompartmentStatsExtras *extras = new xpc::CompartmentStatsExtras;
         nsCString cName;
         GetCompartmentName(c, cName, true);
 
         // Get the compartment's global.
-        nsXPConnect *xpc = nsXPConnect::GetXPConnect();
+        nsXPConnect *xpc = nsXPConnect::XPConnect();
         AutoSafeJSContext cx;
         bool needZone = true;
         RootedObject global(cx, JS_GetGlobalForCompartmentOrNull(cx, c));
         if (global) {
             // Need to enter the compartment, otherwise GetNativeOfWrapper()
             // might crash.
             JSAutoCompartment ac(cx, global);
             nsISupports *native = xpc->GetNativeOfWrapper(cx, global);
@@ -2650,18 +2649,17 @@ SourceHook(JSContext *cx, JS::Handle<JSS
     xpc::Throw(cx, rv);
     return false;
   }
 
   return true;
 }
 
 XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
- : mXPConnect(aXPConnect),
-   mJSRuntime(nullptr),
+   : mJSRuntime(nullptr),
    mJSContextStack(new XPCJSContextStack()),
    mCallContext(nullptr),
    mAutoRoots(nullptr),
    mResolveName(JSID_VOID),
    mResolvingWrapper(nullptr),
    mWrappedJSMap(JSObject2WrappedJSMap::newMap(XPC_JS_MAP_SIZE)),
    mWrappedJSClassMap(IID2WrappedJSClassMap::newMap(XPC_JS_CLASS_MAP_SIZE)),
    mIID2NativeInterfaceMap(IID2NativeInterfaceMap::newMap(XPC_NATIVE_INTERFACE_MAP_SIZE)),
@@ -2910,17 +2908,16 @@ NativeSetDumpEnumerator(JSDHashTable *ta
 
 void
 XPCJSRuntime::DebugDump(int16_t depth)
 {
 #ifdef DEBUG
     depth--;
     XPC_LOG_ALWAYS(("XPCJSRuntime @ %x", this));
         XPC_LOG_INDENT();
-        XPC_LOG_ALWAYS(("mXPConnect @ %x", mXPConnect));
         XPC_LOG_ALWAYS(("mJSRuntime @ %x", mJSRuntime));
         XPC_LOG_ALWAYS(("mMapLock @ %x", mMapLock));
 
         XPC_LOG_ALWAYS(("mWrappedJSToReleaseArray @ %x with %d wrappers(s)", \
                         &mWrappedJSToReleaseArray,
                         mWrappedJSToReleaseArray.Length()));
 
         int cxCount = 0;
@@ -2999,18 +2996,18 @@ XPCRootSetElem::AddToRootSet(XPCLock *lo
         mNext->mSelfp = &mNext;
     }
     *listHead = this;
 }
 
 void
 XPCRootSetElem::RemoveFromRootSet(XPCLock *lock)
 {
-    if (nsXPConnect *xpc = nsXPConnect::GetXPConnect())
-        JS::PokeGC(xpc->GetRuntime()->GetJSRuntime());
+    nsXPConnect *xpc = nsXPConnect::XPConnect();
+    JS::PokeGC(xpc->GetRuntime()->GetJSRuntime());
 
     NS_ASSERTION(mSelfp, "Must be linked");
 
     XPCAutoLock autoLock(lock);
 
     NS_ASSERTION(*mSelfp == this, "Link invariant");
     *mSelfp = mNext;
     if (mNext)
--- a/js/xpconnect/src/XPCJSWeakReference.cpp
+++ b/js/xpconnect/src/XPCJSWeakReference.cpp
@@ -20,17 +20,17 @@ nsresult xpcJSWeakReference::Init(JSCont
         return NS_OK;
 
     JS::RootedObject obj(cx, &object.toObject());
 
     XPCCallContext ccx(NATIVE_CALLER, cx);
 
     // See if the object is a wrapped native that supports weak references.
     nsISupports* supports =
-        nsXPConnect::GetXPConnect()->GetNativeOfWrapper(cx, obj);
+        nsXPConnect::XPConnect()->GetNativeOfWrapper(cx, obj);
     nsCOMPtr<nsISupportsWeakReference> supportsWeakRef =
         do_QueryInterface(supports);
     if (supportsWeakRef) {
         supportsWeakRef->GetWeakReference(getter_AddRefs(mReferent));
         if (mReferent) {
             return NS_OK;
         }
     }
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -60,17 +60,17 @@ LookupInterfaceOrAncestor(uint32_t table
 {
     const xpc_qsHashEntry *entry = LookupEntry(tableSize, table, iid);
     if (!entry) {
         /*
          * On a miss, we have to search for every interface the object
          * supports, including ancestors.
          */
         nsCOMPtr<nsIInterfaceInfo> info;
-        if (NS_FAILED(nsXPConnect::GetXPConnect()->GetInfoForIID(&iid, getter_AddRefs(info))))
+        if (NS_FAILED(nsXPConnect::XPConnect()->GetInfoForIID(&iid, getter_AddRefs(info))))
             return nullptr;
 
         const nsIID *piid;
         for (;;) {
             nsCOMPtr<nsIInterfaceInfo> parent;
             if (NS_FAILED(info->GetParent(getter_AddRefs(parent))) ||
                 !parent ||
                 NS_FAILED(parent->GetIIDShared(&piid))) {
--- a/js/xpconnect/src/XPCThrower.cpp
+++ b/js/xpconnect/src/XPCThrower.cpp
@@ -236,17 +236,17 @@ XPCThrower::ThrowExceptionObject(JSConte
         // context (i.e., not chrome), rethrow the original value.
         if (!IsCallerChrome(cx) &&
             (xpcEx = do_QueryInterface(e)) &&
             NS_SUCCEEDED(xpcEx->StealJSVal(thrown.address()))) {
             if (!JS_WrapValue(cx, thrown.address()))
                 return false;
             JS_SetPendingException(cx, thrown);
             success = true;
-        } else if ((xpc = nsXPConnect::GetXPConnect())) {
+        } else if ((xpc = nsXPConnect::XPConnect())) {
             JS::RootedObject glob(cx, JS_GetGlobalForScopeChain(cx));
             if (!glob)
                 return false;
 
             nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
             nsresult rv = xpc->WrapNative(cx, glob, e,
                                           NS_GET_IID(nsIException),
                                           getter_AddRefs(holder));
--- a/js/xpconnect/src/XPCVariant.cpp
+++ b/js/xpconnect/src/XPCVariant.cpp
@@ -345,22 +345,21 @@ JSBool XPCVariant::InitializeData(JSCont
         mData.u.array.mArrayCount = len;
         mData.u.array.mArrayType = type.TagPart();
 
         return true;
     }
 
     // XXX This could be smarter and pick some more interesting iface.
 
-    nsXPConnect*  xpc;
+    nsXPConnect*  xpc = nsXPConnect::XPConnect();
     nsCOMPtr<nsISupports> wrapper;
     const nsIID& iid = NS_GET_IID(nsISupports);
 
-    return nullptr != (xpc = nsXPConnect::GetXPConnect()) &&
-           NS_SUCCEEDED(xpc->WrapJS(cx, jsobj,
+    return NS_SUCCEEDED(xpc->WrapJS(cx, jsobj,
                                     iid, getter_AddRefs(wrapper))) &&
            NS_SUCCEEDED(nsVariant::SetFromInterface(&mData, iid, wrapper));
 }
 
 NS_IMETHODIMP
 XPCVariant::GetAsJSVal(jsval* result)
 {
   NS_PRECONDITION(result, "null result arg.");
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -120,17 +120,17 @@ nsXPCWrappedJSClass::GetNewOrUsed(JSCont
         XPCAutoLock lock(rt->GetMapLock());
         IID2WrappedJSClassMap* map = rt->GetWrappedJSClassMap();
         clazz = map->Find(aIID);
         NS_IF_ADDREF(clazz);
     }
 
     if (!clazz) {
         nsCOMPtr<nsIInterfaceInfo> info;
-        nsXPConnect::GetXPConnect()->GetInfoForIID(&aIID, getter_AddRefs(info));
+        nsXPConnect::XPConnect()->GetInfoForIID(&aIID, getter_AddRefs(info));
         if (info) {
             bool canScript, isBuiltin;
             if (NS_SUCCEEDED(info->IsScriptable(&canScript)) && canScript &&
                 NS_SUCCEEDED(info->IsBuiltinClass(&isBuiltin)) && !isBuiltin &&
                 nsXPConnect::IsISupportsDescendant(info)) {
                 clazz = new nsXPCWrappedJSClass(cx, aIID, info);
                 if (clazz && !clazz->mDescriptors)
                     NS_RELEASE(clazz);  // sets clazz to nullptr
@@ -235,17 +235,17 @@ nsXPCWrappedJSClass::CallQueryInterfaceO
     // Ensure that we are asking for a scriptable interface.
     // NB:  It's important for security that this check is here rather
     // than later, since it prevents untrusted objects from implementing
     // some interfaces in JS and aggregating a trusted object to
     // implement intentionally (for security) unscriptable interfaces.
     // We so often ask for nsISupports that we can short-circuit the test...
     if (!aIID.Equals(NS_GET_IID(nsISupports))) {
         nsCOMPtr<nsIInterfaceInfo> info;
-        nsXPConnect::GetXPConnect()->GetInfoForIID(&aIID, getter_AddRefs(info));
+        nsXPConnect::XPConnect()->GetInfoForIID(&aIID, getter_AddRefs(info));
         if (!info)
             return nullptr;
         bool canScript, isBuiltin;
         if (NS_FAILED(info->IsScriptable(&canScript)) || !canScript ||
             NS_FAILED(info->IsBuiltinClass(&isBuiltin)) || isBuiltin)
             return nullptr;
     }
 
@@ -271,17 +271,17 @@ nsXPCWrappedJSClass::CallQueryInterfaceO
 
             if (JS_GetPendingException(cx, jsexception.address())) {
                 nsresult rv;
                 if (jsexception.isObject()) {
                     // XPConnect may have constructed an object to represent a
                     // C++ QI failure. See if that is the case.
                     nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
 
-                    nsXPConnect::GetXPConnect()->
+                    nsXPConnect::XPConnect()->
                         GetWrappedNativeOfJSObject(cx,
                                                    &jsexception.toObject(),
                                                    getter_AddRefs(wrapper));
 
                     if (wrapper) {
                         nsCOMPtr<nsIException> exception =
                             do_QueryWrappedNative(wrapper);
                         if (exception &&
@@ -679,17 +679,17 @@ nsXPCWrappedJSClass::DelegatedQueryInter
 
     if (aIID.Equals(NS_GET_IID(nsISecurityCheckedComponent))) {
         // XXX This code checks to see if the given object has chrome (also
         // known as system) principals. It really wants to do a
         // UniversalXPConnect type check.
 
         *aInstancePtr = nullptr;
 
-        nsXPConnect *xpc = nsXPConnect::GetXPConnect();
+        nsXPConnect *xpc = nsXPConnect::XPConnect();
         nsCOMPtr<nsIScriptSecurityManager> secMan =
             do_QueryInterface(xpc->GetDefaultSecurityManager());
         if (!secMan)
             return NS_NOINTERFACE;
 
         RootedObject selfObj(ccx, self->GetJSObject());
         nsCOMPtr<nsIPrincipal> objPrin;
         nsresult rv = secMan->GetObjectPrincipal(ccx, selfObj,
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -2982,28 +2982,16 @@ XPCWrappedNative::GetObjectPrincipal() c
         else
             principal->Equals(objPrin->GetPrincipal(), &equal);
         NS_ASSERTION(equal, "Principal mismatch.  Expect bad things to happen");
     }
 #endif
     return principal;
 }
 
-/* readonly attribute nsIXPConnect XPConnect; */
-NS_IMETHODIMP XPCWrappedNative::GetXPConnect(nsIXPConnect * *aXPConnect)
-{
-    if (IsValid()) {
-        nsIXPConnect* temp = GetRuntime()->GetXPConnect();
-        NS_IF_ADDREF(temp);
-        *aXPConnect = temp;
-    } else
-        *aXPConnect = nullptr;
-    return NS_OK;
-}
-
 /* XPCNativeInterface FindInterfaceWithMember (in JSHandleId name); */
 NS_IMETHODIMP XPCWrappedNative::FindInterfaceWithMember(HandleId name,
                                                         nsIInterfaceInfo * *_retval)
 {
     XPCNativeInterface* iface;
     XPCNativeMember*  member;
 
     if (GetSet()->FindMember(name, &member, &iface) && iface) {
--- a/js/xpconnect/src/XPCWrappedNativeInfo.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeInfo.cpp
@@ -3,17 +3,20 @@
 /* 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/. */
 
 /* Manage the shared info about interfaces for use by wrappedNatives. */
 
 #include "xpcprivate.h"
 
+#include "mozilla/XPTInterfaceInfoManager.h"
+
 using namespace JS;
+using namespace mozilla;
 
 /***************************************************************************/
 
 // XPCNativeMember
 
 // static
 JSBool
 XPCNativeMember::GetCallInfo(JSObject* funobj,
@@ -125,17 +128,17 @@ XPCNativeInterface::GetNewOrUsed(XPCCall
         XPCAutoLock lock(rt->GetMapLock());
         iface = map->Find(*iid);
     }
 
     if (iface)
         return iface;
 
     nsCOMPtr<nsIInterfaceInfo> info;
-    ccx.GetXPConnect()->GetInfoForIID(iid, getter_AddRefs(info));
+    XPTInterfaceInfoManager::GetSingleton()->GetInfoForIID(iid, getter_AddRefs(info));
     if (!info)
         return nullptr;
 
     iface = NewInstance(ccx, info);
     if (!iface)
         return nullptr;
 
     {   // scoped lock
@@ -198,17 +201,17 @@ XPCNativeInterface::GetNewOrUsed(XPCCall
     return iface;
 }
 
 // static
 XPCNativeInterface*
 XPCNativeInterface::GetNewOrUsed(XPCCallContext& ccx, const char* name)
 {
     nsCOMPtr<nsIInterfaceInfo> info;
-    ccx.GetXPConnect()->GetInfoForName(name, getter_AddRefs(info));
+    XPTInterfaceInfoManager::GetSingleton()->GetInfoForName(name, getter_AddRefs(info));
     return info ? GetNewOrUsed(ccx, info) : nullptr;
 }
 
 // static
 XPCNativeInterface*
 XPCNativeInterface::GetISupports(XPCCallContext& ccx)
 {
     // XXX We should optimize this to cache this common XPCNativeInterface.
--- a/js/xpconnect/src/nsCxPusher.cpp
+++ b/js/xpconnect/src/nsCxPusher.cpp
@@ -112,23 +112,17 @@ nsCxPusher::Push(JSContext *cx)
   mScx = GetScriptContextFromJSContext(cx);
 
   DoPush(cx);
 }
 
 void
 nsCxPusher::DoPush(JSContext* cx)
 {
-  nsIXPConnect *xpc = nsXPConnect::GetXPConnect();
-  if (!xpc) {
-    // If someone tries to push a cx when we don't have the relevant state,
-    // it's probably safest to just crash.
-    MOZ_CRASH();
-  }
-
+  nsXPConnect *xpc = nsXPConnect::XPConnect();
   // NB: The GetDynamicScriptContext is historical and might not be sane.
   if (cx && nsJSUtils::GetDynamicScriptContext(cx) &&
       xpc::IsJSContextOnStack(cx))
   {
     // If the context is on the stack, that means that a script
     // is running at the moment in the context.
     mScriptIsRunning = true;
   }
@@ -166,30 +160,29 @@ nsCxPusher::Pop()
     mScx = nullptr;
     mPushedSomething = false;
 
     NS_ASSERTION(!mScriptIsRunning, "Huh, this can't be happening, "
                  "mScriptIsRunning can't be set here!");
 
     return;
   }
-  MOZ_ASSERT(nsXPConnect::GetXPConnect());
 
   // Leave the request before popping.
   mAutoRequest.destroyIfConstructed();
 
   // When we push a context, we may save the frame chain and pretend like we
   // haven't entered any compartment. This gets restored on Pop(), but we can
   // run into trouble if a Push/Pop are interleaved with a
   // JSAutoEnterCompartment. Make sure the compartment depth right before we
   // pop is the same as it was right after we pushed.
   MOZ_ASSERT_IF(mPushedContext, mCompartmentDepthOnEntry ==
                                 js::GetEnterCompartmentDepth(mPushedContext));
   DebugOnly<JSContext*> stackTop;
-  MOZ_ASSERT(mPushedContext == nsXPConnect::GetXPConnect()->GetCurrentJSContext());
+  MOZ_ASSERT(mPushedContext == nsXPConnect::XPConnect()->GetCurrentJSContext());
   xpc::PopJSContext();
 
   if (!mScriptIsRunning && mScx) {
     // No JS is running in the context, but executing the event handler might have
     // caused some JS to run. Tell the script context that it's done.
 
     mScx->ScriptEvaluated(true);
   }
@@ -215,17 +208,17 @@ AutoJSContext::AutoJSContext(bool aSafe 
 
 void
 AutoJSContext::Init(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
 {
   MOZ_ASSERT(!mCx, "mCx should not be initialized!");
 
   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
-  nsIXPConnect *xpc = nsXPConnect::GetXPConnect();
+  nsXPConnect *xpc = nsXPConnect::XPConnect();
   if (!aSafe) {
     mCx = xpc->GetCurrentJSContext();
   }
 
   if (!mCx) {
     mCx = xpc->GetSafeJSContext();
     mPusher.Push(mCx);
   }
@@ -238,14 +231,14 @@ AutoJSContext::operator JSContext*()
 
 AutoSafeJSContext::AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
   : AutoJSContext(true MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
 {
 }
 
 AutoPushJSContext::AutoPushJSContext(JSContext *aCx) : mCx(aCx)
 {
-  if (mCx && mCx != nsXPConnect::GetXPConnect()->GetCurrentJSContext()) {
+  if (mCx && mCx != nsXPConnect::XPConnect()->GetCurrentJSContext()) {
     mPusher.Push(mCx);
   }
 }
 
 } // namespace mozilla
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -132,58 +132,39 @@ nsXPConnect::~nsXPConnect()
 
     delete mRuntime;
 
     gSelf = nullptr;
     gOnceAliveNowDead = true;
 }
 
 // static
-nsXPConnect*
-nsXPConnect::GetXPConnect()
-{
-    // Do a release-mode assert that we're not doing anything significant in
-    // XPConnect off the main thread. If you're an extension developer hitting
-    // this, you need to change your code. See bug 716167.
-    if (!MOZ_LIKELY(NS_IsMainThread() || NS_IsCycleCollectorThread()))
-        MOZ_CRASH();
-
-    if (!gSelf) {
-        if (gOnceAliveNowDead)
-            return nullptr;
-        gSelf = new nsXPConnect();
-        if (!gSelf)
-            return nullptr;
+void
+    nsXPConnect::InitStatics()
+    {
+    gSelf = new nsXPConnect();
+    gOnceAliveNowDead = false;
+    if (!gSelf->mRuntime) {
+        NS_RUNTIMEABORT("Couldn't create XPCJSRuntime.");
+    }
 
-        if (!gSelf->mRuntime) {
-            NS_RUNTIMEABORT("Couldn't create XPCJSRuntime.");
-        }
-
-        // Initial extra ref to keep the singleton alive
-        // balanced by explicit call to ReleaseXPConnectSingleton()
-        NS_ADDREF(gSelf);
+    // Initial extra ref to keep the singleton alive
+    // balanced by explicit call to ReleaseXPConnectSingleton()
+    NS_ADDREF(gSelf);
 
-        // Set XPConnect as the main thread observer.
-        //
-        // The cycle collector sometimes calls GetXPConnect, but it should never
-        // be the one that initializes gSelf.
-        MOZ_ASSERT(NS_IsMainThread());
-        if (NS_FAILED(nsThread::SetMainThreadObserver(gSelf))) {
-            NS_RELEASE(gSelf);
-            // Fall through to returning null
-        }
+    // Set XPConnect as the main thread observer.
+    if (NS_FAILED(nsThread::SetMainThreadObserver(gSelf))) {
+        MOZ_CRASH();
     }
-    return gSelf;
 }
 
-// static
 nsXPConnect*
 nsXPConnect::GetSingleton()
 {
-    nsXPConnect* xpc = nsXPConnect::GetXPConnect();
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     NS_IF_ADDREF(xpc);
     return xpc;
 }
 
 // static
 void
 nsXPConnect::ReleaseXPConnectSingleton()
 {
@@ -225,18 +206,17 @@ nsXPConnect::ReleaseXPConnectSingleton()
 #endif
     }
 }
 
 // static
 XPCJSRuntime*
 nsXPConnect::GetRuntimeInstance()
 {
-    nsXPConnect* xpc = GetXPConnect();
-    NS_ASSERTION(xpc, "Must not be called if XPC failed to initialize");
+    nsXPConnect* xpc = XPConnect();
     return xpc->GetRuntime();
 }
 
 // static
 JSBool
 nsXPConnect::IsISupportsDescendant(nsIInterfaceInfo* info)
 {
     bool found = false;
@@ -2046,17 +2026,17 @@ nsXPConnect::CheckForDebugMode(JSRuntime
 }
 #endif //#ifdef MOZ_JSDEBUGGER
 
 
 NS_EXPORT_(void)
 xpc_ActivateDebugMode()
 {
     XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
-    nsXPConnect::GetXPConnect()->SetDebugModeWhenPossible(true, true);
+    nsXPConnect::XPConnect()->SetDebugModeWhenPossible(true, true);
     nsXPConnect::CheckForDebugMode(rt->GetJSRuntime());
 }
 
 /* virtual */
 JSContext*
 nsXPConnect::GetCurrentJSContext()
 {
     JSContext *cx = GetRuntime()->GetJSContextStack()->Peek();
@@ -2071,17 +2051,17 @@ nsXPConnect::GetSafeJSContext()
 }
 
 namespace xpc {
 
 bool
 PushJSContext(JSContext *aCx)
 {
     // JSD mumbo jumbo.
-    nsXPConnect *xpc = nsXPConnect::GetXPConnect();
+    nsXPConnect *xpc = nsXPConnect::XPConnect();
     JSRuntime *rt = XPCJSRuntime::Get()->GetJSRuntime();
     if (xpc::gDebugMode != xpc::gDesiredDebugMode) {
         if (!xpc::gDesiredDebugMode) {
             /* Turn off debug mode immediately, even if JS code is currently
                running. */
             xpc->CheckForDebugMode(rt);
         } else {
             bool runningJS = false;
@@ -2246,21 +2226,17 @@ Base64Decode(JSContext *cx, JS::Value va
     *out = STRING_TO_JSVAL(str);
     return true;
 }
 
 void
 DumpJSHeap(FILE* file)
 {
     NS_ABORT_IF_FALSE(NS_IsMainThread(), "Must dump GC heap on main thread.");
-    nsXPConnect* xpc = nsXPConnect::GetXPConnect();
-    if (!xpc) {
-        NS_ERROR("Failed to get nsXPConnect instance!");
-        return;
-    }
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
     js::DumpHeapComplete(xpc->GetRuntime()->GetJSRuntime(), file);
 }
 
 void
 SetLocationForGlobal(JSObject *global, const nsACString& location)
 {
     MOZ_ASSERT(global);
     EnsureCompartmentPrivate(global)->SetLocation(location);
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -104,16 +104,17 @@
 #include "jsfriendapi.h"
 #include "js/HeapAPI.h"
 #include "jswrapper.h"
 #include "nscore.h"
 #include "nsXPCOM.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCycleCollectionJSRuntime.h"
+#include "nsCycleCollectorUtils.h"
 #include "nsDebug.h"
 #include "nsISupports.h"
 #include "nsIServiceManager.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIComponentManager.h"
 #include "nsIComponentRegistrar.h"
 #include "nsISupportsPrimitives.h"
 #include "nsMemory.h"
@@ -471,18 +472,27 @@ public:
     NS_DECL_NSIXPCONNECT
     NS_DECL_NSITHREADOBSERVER
     NS_DECL_NSIJSRUNTIMESERVICE
     NS_DECL_NSIJSENGINETELEMETRYSTATS
 
     // non-interface implementation
 public:
     // These get non-addref'd pointers
-    static nsXPConnect*  GetXPConnect();
-    static nsXPConnect*  FastGetXPConnect() { return gSelf ? gSelf : GetXPConnect(); }
+    static nsXPConnect*  XPConnect()
+    {
+        // Do a release-mode assert that we're not doing anything significant in
+        // XPConnect off the main thread. If you're an extension developer hitting
+        // this, you need to change your code. See bug 716167.
+        if (!MOZ_LIKELY(NS_IsMainThread() || NS_IsCycleCollectorThread()))
+            MOZ_CRASH();
+
+        return gSelf;
+    }
+
     static XPCJSRuntime* GetRuntimeInstance();
     XPCJSRuntime* GetRuntime() {return mRuntime;}
 
 #ifdef DEBUG
     void SetObjectToUnlink(void* aObject);
     void AssertNoObjectsToTrace(void* aPossibleJSHolder);
 #endif
 
@@ -501,17 +511,17 @@ public:
         {return mDefaultSecurityManagerFlags;}
 
     // This returns an AddRef'd pointer. It does not do this with an 'out' param
     // only because this form is required by the generic module macro:
     // NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
     static nsXPConnect* GetSingleton();
 
     // Called by module code in dll startup
-    static void InitStatics() { gSelf = nullptr; gOnceAliveNowDead = false; }
+    static void InitStatics();
     // Called by module code on dll shutdown.
     static void ReleaseXPConnectSingleton();
 
     virtual ~nsXPConnect();
 
     JSBool IsShuttingDown() const {return mShuttingDown;}
 
     nsresult GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info);
@@ -639,20 +649,19 @@ public:
 
 // no virtuals. no refcounting.
 class XPCJSContextStack;
 class XPCIncrementalReleaseRunnable;
 class XPCJSRuntime
 {
 public:
     static XPCJSRuntime* newXPCJSRuntime(nsXPConnect* aXPConnect);
-    static XPCJSRuntime* Get() { return nsXPConnect::GetXPConnect()->GetRuntime(); }
+    static XPCJSRuntime* Get() { return nsXPConnect::XPConnect()->GetRuntime(); }
 
     JSRuntime*     GetJSRuntime() const {return mJSRuntime;}
-    nsXPConnect*   GetXPConnect() const {return mXPConnect;}
 
     XPCJSContextStack* GetJSContextStack() {return mJSContextStack;}
     void DestroyJSContextStack();
 
     XPCCallContext*  GetCallContext() const {return mCallContext;}
     XPCCallContext*  SetCallContext(XPCCallContext* ccx)
         {XPCCallContext* old = mCallContext; mCallContext = ccx; return old;}
 
@@ -897,17 +906,16 @@ private:
     void ReleaseIncrementally(nsTArray<nsISupports *> &array);
     bool IsRuntimeActive();
     PRTime TimeSinceLastRuntimeStateChange();
 
     static const char* mStrings[IDX_TOTAL_COUNT];
     jsid mStrIDs[IDX_TOTAL_COUNT];
     jsval mStrJSVals[IDX_TOTAL_COUNT];
 
-    nsXPConnect*             mXPConnect;
     JSRuntime*               mJSRuntime;
     XPCJSContextStack*       mJSContextStack;
     XPCCallContext*          mCallContext;
     AutoMarkingPtr*          mAutoRoots;
     jsid                     mResolveName;
     XPCWrappedNative*        mResolvingWrapper;
     JSObject2WrappedJSMap*   mWrappedJSMap;
     IID2WrappedJSClassMap*   mWrappedJSClassMap;
@@ -1045,17 +1053,17 @@ public:
             NS_ASSERTION(CallerTypeIsKnown(),"missing caller type set somewhere");
             if (!CallerTypeIsJavaScript())
                 return nullptr;
             if (mSecurityManager) {
                 if (flags & mSecurityManagerFlags)
                     return mSecurityManager;
             } else {
                 nsIXPCSecurityManager* mgr;
-                nsXPConnect* xpc = mRuntime->GetXPConnect();
+                nsXPConnect* xpc = nsXPConnect::XPConnect();
                 mgr = xpc->GetDefaultSecurityManager();
                 if (mgr && (flags & xpc->GetDefaultSecurityManagerFlags()))
                     return mgr;
             }
             return nullptr;
         }
 
     void DebugDump(int16_t depth);
@@ -1130,17 +1138,16 @@ public:
                    unsigned argc           = NO_ARGS,
                    jsval *argv             = nullptr,
                    jsval *rval             = nullptr);
 
     virtual ~XPCCallContext();
 
     inline JSBool                       IsValid() const ;
 
-    inline nsXPConnect*                 GetXPConnect() const ;
     inline XPCJSRuntime*                GetRuntime() const ;
     inline XPCContext*                  GetXPCContext() const ;
     inline JSContext*                   GetJSContext() const ;
     inline JSBool                       GetContextPopRequired() const ;
     inline XPCContext::LangType         GetCallerLanguage() const ;
     inline XPCContext::LangType         GetPrevCallerLanguage() const ;
     inline XPCCallContext*              GetPrevCallContext() const ;
 
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -289,19 +289,19 @@ WrapperFactory::PrepareForWrapping(JSCon
     // NB: Passing a holder here inhibits slim wrappers under
     // WrapNativeToJSVal.
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
 
     // This public WrapNativeToJSVal API enters the compartment of 'wrapScope'
     // so we don't have to.
     RootedValue v(cx);
     nsresult rv =
-        nsXPConnect::FastGetXPConnect()->WrapNativeToJSVal(cx, wrapScope, wn->Native(), nullptr,
-                                                           &NS_GET_IID(nsISupports), false,
-                                                           v.address(), getter_AddRefs(holder));
+        nsXPConnect::XPConnect()->WrapNativeToJSVal(cx, wrapScope, wn->Native(), nullptr,
+                                                    &NS_GET_IID(nsISupports), false,
+                                                    v.address(), getter_AddRefs(holder));
     if (NS_SUCCEEDED(rv)) {
         obj = JSVAL_TO_OBJECT(v);
         NS_ASSERTION(IS_WN_WRAPPER(obj), "bad object");
 
         // Because the underlying native didn't have a PreCreate hook, we had
         // to a new (or possibly pre-existing) XPCWN in our compartment.
         // This could be a problem for chrome code that passes XPCOM objects
         // across compartments, because the effects of QI would disappear across
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -867,19 +867,19 @@ wrappedJSObject_getter(JSContext *cx, Ha
     return WrapperFactory::WaiveXrayAndWrap(cx, vp.address());
 }
 
 static JSBool
 WrapURI(JSContext *cx, nsIURI *uri, MutableHandleValue vp)
 {
     RootedObject scope(cx, JS_GetGlobalForScopeChain(cx));
     nsresult rv =
-        nsXPConnect::FastGetXPConnect()->WrapNativeToJSVal(cx, scope, uri, nullptr,
-                                                           &NS_GET_IID(nsIURI), true,
-                                                           vp.address(), nullptr);
+        nsXPConnect::XPConnect()->WrapNativeToJSVal(cx, scope, uri, nullptr,
+                                                    &NS_GET_IID(nsIURI), true,
+                                                    vp.address(), nullptr);
     if (NS_FAILED(rv)) {
         XPCThrower::Throw(rv, cx);
         return false;
     }
     return true;
 }
 
 static JSBool
@@ -906,19 +906,19 @@ nodePrincipal_getter(JSContext *cx, Hand
     nsCOMPtr<nsINode> node = do_QueryInterfaceNative(cx, wrapper);
     if (!node) {
         JS_ReportError(cx, "Unexpected object");
         return false;
     }
 
     RootedObject scope(cx, JS_GetGlobalForScopeChain(cx));
     nsresult rv =
-        nsXPConnect::FastGetXPConnect()->WrapNativeToJSVal(cx, scope, node->NodePrincipal(), nullptr,
-                                                           &NS_GET_IID(nsIPrincipal), true,
-                                                           vp.address(), nullptr);
+        nsXPConnect::XPConnect()->WrapNativeToJSVal(cx, scope, node->NodePrincipal(), nullptr,
+                                                    &NS_GET_IID(nsIPrincipal), true,
+                                                    vp.address(), nullptr);
     if (NS_FAILED(rv)) {
         XPCThrower::Throw(rv, cx);
         return false;
     }
     return true;
 }
 
 bool
@@ -1942,16 +1942,16 @@ do_QueryInterfaceNative(JSContext* cx, H
         RootedObject target(cx, XrayTraits::getTargetObject(wrapper));
         if (GetXrayType(target) == XrayForDOMObject) {
             nativeSupports = UnwrapDOMObjectToISupports(target);
         } else {
             XPCWrappedNative *wn = GetWrappedNative(target);
             nativeSupports = wn->Native();
         }
     } else {
-        nsIXPConnect *xpc = nsXPConnect::GetXPConnect();
+        nsIXPConnect *xpc = nsXPConnect::XPConnect();
         nativeSupports = xpc->GetNativeOfWrapper(cx, wrapper);
     }
 
     return nsQueryInterface(nativeSupports);
 }
 
 }
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -7,16 +7,17 @@
 
 /* rendering object for CSS "display: flex" */
 
 #include "nsFlexContainerFrame.h"
 #include "nsContentUtils.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsDisplayList.h"
 #include "nsLayoutUtils.h"
+#include "nsPlaceholderFrame.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "prlog.h"
 #include <algorithm>
 
 using namespace mozilla::css;
 using namespace mozilla::layout;
 
@@ -533,21 +534,27 @@ IsOrderLEQWithDOMFallback(nsIFrame* aFra
 
   if (aFrame1 == aFrame2) {
     // Anything is trivially LEQ itself, so we return "true" here... but it's
     // probably bad if we end up actually needing this, so let's assert.
     NS_ERROR("Why are we checking if a frame is LEQ itself?");
     return true;
   }
 
-  int32_t order1 = aFrame1->StylePosition()->mOrder;
-  int32_t order2 = aFrame2->StylePosition()->mOrder;
+  // If we've got a placeholder frame, use its out-of-flow frame's 'order' val.
+  {
+    nsIFrame* aRealFrame1 = nsPlaceholderFrame::GetRealFrameFor(aFrame1);
+    nsIFrame* aRealFrame2 = nsPlaceholderFrame::GetRealFrameFor(aFrame2);
 
-  if (order1 != order2) {
-    return order1 < order2;
+    int32_t order1 = aRealFrame1->StylePosition()->mOrder;
+    int32_t order2 = aRealFrame2->StylePosition()->mOrder;
+
+    if (order1 != order2) {
+      return order1 < order2;
+    }
   }
 
   // The "order" values are equal, so we need to fall back on DOM comparison.
   // For that, we need to dig through any anonymous box wrapper frames to find
   // the actual frame that corresponds to our child content.
   aFrame1 = GetFirstNonAnonBoxDescendant(aFrame1);
   aFrame2 = GetFirstNonAnonBoxDescendant(aFrame2);
   MOZ_ASSERT(aFrame1 && aFrame2,
@@ -598,18 +605,22 @@ IsOrderLEQWithDOMFallback(nsIFrame* aFra
  */
 bool
 IsOrderLEQ(nsIFrame* aFrame1,
            nsIFrame* aFrame2)
 {
   MOZ_ASSERT(aFrame1->IsFlexItem() && aFrame2->IsFlexItem(),
              "this method only intended for comparing flex items");
 
-  int32_t order1 = aFrame1->StylePosition()->mOrder;
-  int32_t order2 = aFrame2->StylePosition()->mOrder;
+  // If we've got a placeholder frame, use its out-of-flow frame's 'order' val.
+  nsIFrame* aRealFrame1 = nsPlaceholderFrame::GetRealFrameFor(aFrame1);
+  nsIFrame* aRealFrame2 = nsPlaceholderFrame::GetRealFrameFor(aFrame2);
+
+  int32_t order1 = aRealFrame1->StylePosition()->mOrder;
+  int32_t order2 = aRealFrame2->StylePosition()->mOrder;
 
   return order1 <= order2;
 }
 
 bool
 nsFlexContainerFrame::IsHorizontal()
 {
   const FlexboxAxisTracker axisTracker(this);
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-ordinal/box-ordinal-with-out-of-flow-1-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <style>
+    #container { display: -moz-box; }
+    #highOrdinal {
+      background: lime;
+      height: 100px; width: 100px;
+    }
+  </style>
+</head>
+<body>
+  <div id="container">
+    <div id="highOrdinal"></div>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-ordinal/box-ordinal-with-out-of-flow-1.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!-- Testcase for whether we honor "-moz-box-ordinal-group" on
+     absolutely-positioned elements within a -moz-box. Specifically,
+     we test whether it affects their paint-order (as it should, since
+     it reorders the frame tree).
+-->
+<html>
+<head>
+  <style>
+    #container { display: -moz-box; }
+    #lowOrdinal {
+      position: absolute;
+      -moz-box-ordinal-group: 5;
+      background: red;
+      height: 100px; width: 100px;
+    }
+    #highOrdinal {
+      position: absolute;
+      -moz-box-ordinal-group: 10;
+      background: lime;
+      height: 100px; width: 100px;
+    }
+    #noOrdinal {
+      position: absolute;
+      background: orange;
+      height: 100px; width: 100px;
+    }
+  </style>
+</head>
+<body>
+  <div id="container">
+    <div id="highOrdinal"></div>
+    <div id="lowOrdinal"></div>
+    <div id="noOrdinal"></div>
+  </div>
+</body>
+</html>
--- a/layout/reftests/box-ordinal/reftest.list
+++ b/layout/reftests/box-ordinal/reftest.list
@@ -1,6 +1,7 @@
+== box-ordinal-with-out-of-flow-1.html box-ordinal-with-out-of-flow-1-ref.html
 == dynamic-1-remove-to-none-grouped.xul dynamic-1-ref.xul
 == dynamic-1-add-to-one-grouped.xul dynamic-1-ref.xul
 == dynamic-1-remove-to-one-grouped-1.xul dynamic-1-ref.xul
 fails == dynamic-1-remove-to-one-grouped-2.xul dynamic-1-ref.xul # bug 575500
 == dynamic-1-add-to-two-grouped-1.xul dynamic-1-ref.xul
 == dynamic-1-add-to-two-grouped-2.xul dynamic-1-ref.xul
new file mode 100644
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-paint-ordering-3-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <style>
+    #container { display: flex; }
+    #highOrdinal {
+      background: lime;
+      height: 100px; width: 100px;
+    }
+  </style>
+</head>
+<body>
+  <div id="container">
+    <div id="highOrdinal"></div>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/flexbox/flexbox-paint-ordering-3.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!-- Testcase for whether we honor "order" on absolutely-positioned elements
+     within a flex container. Specifically, we test whether it affects their
+     paint-order (as it should, since it reorders the frame tree).  -->
+<html>
+<head>
+  <style>
+    #container { display: flex; }
+    #lowOrdinal {
+      position: absolute;
+      order: 5;
+      background: red;
+      height: 100px; width: 100px;
+    }
+    #highOrdinal {
+      position: absolute;
+      order: 10;
+      background: lime;
+      height: 100px; width: 100px;
+    }
+    #noOrdinal {
+      position: absolute;
+      background: orange;
+      height: 100px; width: 100px;
+    }
+  </style>
+</head>
+<body>
+  <div id="container">
+    <div id="highOrdinal"></div>
+    <div id="lowOrdinal"></div>
+    <div id="noOrdinal"></div>
+  </div>
+</body>
+</html>
--- a/layout/reftests/flexbox/reftest.list
+++ b/layout/reftests/flexbox/reftest.list
@@ -133,16 +133,17 @@ fuzzy-if(d2d&&layersGPUAccelerated,24,14
 
 # Tests for "min-width" and "min-height" on flex items.
 == flexbox-minSize-horiz-1.xhtml flexbox-minSize-horiz-1-ref.xhtml
 fails == flexbox-minSize-vert-1.xhtml  flexbox-minSize-vert-1-ref.xhtml # bug 852367
 
 # Tests for the order in which we paint flex items
 == flexbox-paint-ordering-1.xhtml flexbox-paint-ordering-1-ref.xhtml
 == flexbox-paint-ordering-2.xhtml flexbox-paint-ordering-2-ref.xhtml
+fails == flexbox-paint-ordering-3.html  flexbox-paint-ordering-3-ref.html # bug 874718
 
 # Tests for handling of absolutely/fixed/relatively-positioned flex items.
 == flexbox-position-absolute-1.xhtml  flexbox-position-absolute-1-ref.xhtml
 == flexbox-position-absolute-2.xhtml  flexbox-position-absolute-2-ref.xhtml
 == flexbox-position-absolute-3.xhtml  flexbox-position-absolute-3-ref.xhtml
 == flexbox-position-absolute-4.xhtml  flexbox-position-absolute-4-ref.xhtml
 == flexbox-position-fixed-3.xhtml     flexbox-position-fixed-3-ref.xhtml
 == flexbox-position-fixed-1.xhtml     flexbox-position-fixed-1-ref.xhtml
--- a/layout/reftests/svg/text/multiple-x-percentages-3.html
+++ b/layout/reftests/svg/text/multiple-x-percentages-3.html
@@ -3,28 +3,24 @@
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <html class="reftest-wait">
 <iframe style="width: 400px; height: 400px; border: 0" src="multiple-x-percentages-3-iframe.svg"></iframe>
 <script>
 var iframe = document.querySelector("iframe");
 
-function doTestPart1() {
+function doTest() {
+  window.removeEventListener("MozReftestInvalidate", doTest);
+
   iframe.style.width = "200px";
   iframe.style.height = "200px";
-  window.removeEventListener("MozReftestInvalidate", doTestPart1);
 
-  window.addEventListener("MozReftestInvalidate", doTestPart2, false);
-  setTimeout(doTestPart2, 4000); // fallback for running outside reftest
-}
-
-function doTestPart2() {
   var text = iframe.contentDocument.querySelectorAll("text");
   text[0].firstChild.nodeValue += "!";
   text[1].firstChild.nodeValue += "!";
 
   document.documentElement.removeAttribute("class");
 }
 
-window.addEventListener("MozReftestInvalidate", doTestPart1, false);
-setTimeout(doTestPart1, 4000); // fallback for running outside reftest
+window.addEventListener("MozReftestInvalidate", doTest, false);
+setTimeout(doTest, 4000); // fallback for running outside reftest
 </script>
--- a/layout/svg/nsSVGTextFrame2.cpp
+++ b/layout/svg/nsSVGTextFrame2.cpp
@@ -4798,18 +4798,18 @@ nsSVGTextFrame2::UpdateGlyphPositioning(
 void
 nsSVGTextFrame2::DoReflow()
 {
   // Since we are going to reflow the anonymous block frame, we will
   // need to update mPositions.
   mPositioningDirty = true;
 
   if (mState & NS_STATE_SVG_NONDISPLAY_CHILD) {
-    // Normally, this flag would be cleared in ReflowSVG(), but that doesn't
-    // get called for non-display frames. We don't want to reflow our
+    // Normally, these dirty flags would be cleared in ReflowSVG(), but that
+    // doesn't get called for non-display frames. We don't want to reflow our
     // descendants every time nsSVGTextFrame2::PaintSVG makes sure that we have
     // valid positions by calling UpdateGlyphPositioning(), so we need to clear
     // these dirty bits. Note that this also breaks an invalidation loop where
     // our descendants invalidate as they reflow, which invalidates rendering
     // observers, which reschedules the frame that is currently painting by
     // referencing us to paint again. See bug 839958 comment 7. Hopefully we
     // will break that loop more convincingly at some point.
     mState &= ~(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
--- a/layout/xul/base/src/nsBoxFrame.cpp
+++ b/layout/xul/base/src/nsBoxFrame.cpp
@@ -30,16 +30,17 @@
 // reflow occurs. The preferred size of a child deep in the hierarchy could change. And this could change
 // any number of syblings around the box. Basically any children in the reflow chain must have their caches cleared
 // so when asked for there current size they can relayout themselves. 
 
 #include "nsBoxLayoutState.h"
 #include "nsBoxFrame.h"
 #include "mozilla/dom/Touch.h"
 #include "nsStyleContext.h"
+#include "nsPlaceholderFrame.h"
 #include "nsPresContext.h"
 #include "nsCOMPtr.h"
 #include "nsINameSpaceManager.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "nsHTMLParts.h"
 #include "nsViewManager.h"
 #include "nsView.h"
@@ -1884,17 +1885,20 @@ nsBoxFrame::SupportsOrdinalsInChildren()
 }
 
 // Helper less-than-or-equal function, used in CheckBoxOrder() as a
 // template-parameter for the sorting functions.
 bool
 IsBoxOrdinalLEQ(nsIFrame* aFrame1,
                 nsIFrame* aFrame2)
 {
-  return aFrame1->GetOrdinal() <= aFrame2->GetOrdinal();
+  // If we've got a placeholder frame, use its out-of-flow frame's ordinal val.
+  nsIFrame* aRealFrame1 = nsPlaceholderFrame::GetRealFrameFor(aFrame1);
+  nsIFrame* aRealFrame2 = nsPlaceholderFrame::GetRealFrameFor(aFrame2);
+  return aRealFrame1->GetOrdinal() <= aRealFrame2->GetOrdinal();
 }
 
 void 
 nsBoxFrame::CheckBoxOrder()
 {
   if (SupportsOrdinalsInChildren() &&
       !nsLayoutUtils::IsFrameListSorted<IsBoxOrdinalLEQ>(mFrames)) {
     nsLayoutUtils::SortFrameList<IsBoxOrdinalLEQ>(mFrames);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -307,29 +307,32 @@ PeerConnectionImpl::PeerConnectionImpl()
   , mSTSThread(NULL)
   , mMedia(NULL)
   , mNumAudioStreams(0)
   , mNumVideoStreams(0)
   , mHaveDataStream(false) {
 #ifdef MOZILLA_INTERNAL_API
   MOZ_ASSERT(NS_IsMainThread());
 #endif
+  CSFLogInfo(logTag, "%s: PeerConnectionImpl constructor for %p",
+             __FUNCTION__, (void *) this);
 }
 
 PeerConnectionImpl::~PeerConnectionImpl()
 {
   // This aborts if not on main thread (in Debug builds)
   PC_AUTO_ENTER_API_CALL_NO_CHECK();
   if (PeerConnectionCtx::isActive()) {
     PeerConnectionCtx::GetInstance()->mPeerConnections.erase(mHandle);
   } else {
     CSFLogError(logTag, "PeerConnectionCtx is already gone. Ignoring...");
   }
 
-  CSFLogInfo(logTag, "%s: PeerConnectionImpl destructor invoked", __FUNCTION__);
+  CSFLogInfo(logTag, "%s: PeerConnectionImpl destructor invoked for %p",
+             __FUNCTION__, (void *) this);
   CloseInt();
 
 #ifdef MOZILLA_INTERNAL_API
   // Deregister as an NSS Shutdown Object
   shutdown(calledFromObject);
 #endif
 
   // Since this and Initialize() occur on MainThread, they can't both be
@@ -691,16 +694,18 @@ PeerConnectionImpl::EnsureDataConnection
     // and we increase the number of streams dynamically as needed.
     return NS_OK;
   }
   mDataConnection = new mozilla::DataChannelConnection(this);
   if (!mDataConnection->Init(5000, aNumstreams, true)) {
     CSFLogError(logTag,"%s DataConnection Init Failed",__FUNCTION__);
     return NS_ERROR_FAILURE;
   }
+  CSFLogDebug(logTag,"%s DataChannelConnection %p attached to %p",
+              __FUNCTION__, (void*) mDataConnection.get(), (void *) this);
 #endif
   return NS_OK;
 }
 
 nsresult
 PeerConnectionImpl::InitializeDataChannel(int track_id,
                                           uint16_t aLocalport,
                                           uint16_t aRemoteport,
@@ -1235,35 +1240,37 @@ PeerConnectionImpl::CheckApiState(bool a
   if (!mMedia)
     return NS_ERROR_FAILURE;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PeerConnectionImpl::Close()
 {
-  CSFLogDebug(logTag, "%s", __FUNCTION__);
+  CSFLogDebug(logTag, "%s: for %p", __FUNCTION__, (void *) this);
   PC_AUTO_ENTER_API_CALL_NO_CHECK();
 
   return CloseInt();
 }
 
 
 nsresult
 PeerConnectionImpl::CloseInt()
 {
   PC_AUTO_ENTER_API_CALL_NO_CHECK();
 
   if (mCall) {
-    CSFLogInfo(logTag, "%s: Closing PeerConnectionImpl; "
-                       "ending call", __FUNCTION__);
+    CSFLogInfo(logTag, "%s: Closing PeerConnectionImpl %p; "
+               "ending call", __FUNCTION__, (void *) this);
     mCall->endCall();
   }
 #ifdef MOZILLA_INTERNAL_API
   if (mDataConnection) {
+    CSFLogInfo(logTag, "%s: Destroying DataChannelConnection %p for %p",
+               __FUNCTION__, (void *) mDataConnection.get(), (void *) this);
     mDataConnection->Destroy();
     mDataConnection = nullptr; // it may not go away until the runnables are dead
   }
 #endif
 
   ShutdownMedia();
 
   // DataConnection will need to stay alive until all threads/runnables exit
--- a/modules/libjar/nsJAR.cpp
+++ b/modules/libjar/nsJAR.cpp
@@ -39,20 +39,20 @@ typedef enum
 class nsJARManifestItem
 {
 public:
   JARManifestItemType mType;
 
   // True if the second step of verification (VerifyEntry) 
   // has taken place:
   bool                entryVerified;
-  
+
   // Not signed, valid, or failure code
   int16_t             status;
-  
+
   // Internal storage of digests
   nsCString           calculatedSectionDigest;
   nsCString           storedEntryDigest;
 
   nsJARManifestItem();
   virtual ~nsJARManifestItem();
 };
 
--- a/netwerk/base/src/ProxyAutoConfig.cpp
+++ b/netwerk/base/src/ProxyAutoConfig.cpp
@@ -520,16 +520,22 @@ private:
       MOZ_COUNT_CTOR(JSRuntimeWrapper);
   }
 
   nsresult Init()
   {
     mRuntime = JS_NewRuntime(sRuntimeHeapSize, JS_NO_HELPER_THREADS);
     NS_ENSURE_TRUE(mRuntime, NS_ERROR_OUT_OF_MEMORY);
 
+    /*
+     * Not setting this will cause JS_CHECK_RECURSION to report false
+     * positives
+     */ 
+    JS_SetNativeStackQuota(mRuntime, 128 * sizeof(size_t) * 1024); 
+
     mContext = JS_NewContext(mRuntime, 0);
     NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY);
 
     JSAutoRequest ar(mContext);
 
     mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, JS::SystemZone);
     NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
 
--- a/netwerk/sctp/datachannel/DataChannel.cpp
+++ b/netwerk/sctp/datachannel/DataChannel.cpp
@@ -213,43 +213,55 @@ DataChannelConnection::Destroy()
   // if we really want it to do true clean shutdowns it can
   // create a dependant Internal object that would remain around
   // until the network shut down the association or timed out.
   LOG(("Destroying DataChannelConnection %p", (void *) this));
   ASSERT_WEBRTC(NS_IsMainThread());
   CloseAll();
 
   MutexAutoLock lock(mLock);
-  if (mSocket && mSocket != mMasterSocket)
-    usrsctp_close(mSocket);
-  if (mMasterSocket)
-    usrsctp_close(mMasterSocket);
+  // If we had a pending reset, we aren't waiting for it - clear the list so
+  // we can deregister this DataChannelConnection without leaking.
+  ClearResets();
 
+  MOZ_ASSERT(mSTS);
+  ASSERT_WEBRTC(NS_IsMainThread());
+  // Finish Destroy on STS thread to avoid bug 876167 - once that's fixed,
+  // the usrsctp_close() calls can move back here (and just proxy the
+  // disconnect_all())
+  RUN_ON_THREAD(mSTS, WrapRunnable(nsRefPtr<DataChannelConnection>(this),
+                                   &DataChannelConnection::DestroyOnSTS,
+                                   mSocket, mMasterSocket),
+                NS_DISPATCH_NORMAL);
+
+  // These will be released on STS
   mSocket = nullptr;
   mMasterSocket = nullptr; // also a flag that we've Destroyed this connection
 
+  // Must do this in Destroy() since we may then delete this object
   if (mUsingDtls) {
     usrsctp_deregister_address(static_cast<void *>(this));
     LOG(("Deregistered %p from the SCTP stack.", static_cast<void *>(this)));
   }
+
   // We can't get any more new callbacks from the SCTP library
   // All existing callbacks have refs to DataChannelConnection
 
   // nsDOMDataChannel objects have refs to DataChannels that have refs to us
+}
 
-  if (mTransportFlow) {
-    MOZ_ASSERT(mSTS);
-    ASSERT_WEBRTC(NS_IsMainThread());
-    RUN_ON_THREAD(mSTS, WrapRunnable(nsRefPtr<DataChannelConnection>(this),
-                                     &DataChannelConnection::disconnect_all),
-                  NS_DISPATCH_NORMAL);
-    // don't release mTransportFlow until we are destroyed in case
-    // runnables are in flight.  We may well have packets to send as the
-    // SCTP lib may have sent a shutdown.
-  }
+void DataChannelConnection::DestroyOnSTS(struct socket *aMasterSocket,
+                                         struct socket *aSocket)
+{
+  if (aSocket && aSocket != aMasterSocket)
+    usrsctp_close(aSocket);
+  if (aMasterSocket)
+    usrsctp_close(aMasterSocket);
+
+  disconnect_all();
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(DataChannelConnection,
                               nsITimerCallback)
 
 bool
 DataChannelConnection::Init(unsigned short aPort, uint16_t aNumStreams, bool aUsingDtls)
 {
@@ -1350,16 +1362,17 @@ DataChannelConnection::HandleAssociation
     } else if (mState == OPEN) {
       LOG(("DataConnection Already OPEN"));
     } else {
       LOG(("Unexpected state: %d", mState));
     }
     break;
   case SCTP_COMM_LOST:
     LOG(("Association change: SCTP_COMM_LOST"));
+    // This association is toast, so also close all the channels -- from mainthread!
     NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
                               DataChannelOnMessageAvailable::ON_DISCONNECTED,
                               this));
     break;
   case SCTP_RESTART:
     LOG(("Association change: SCTP_RESTART"));
     break;
   case SCTP_SHUTDOWN_COMP:
@@ -1529,16 +1542,35 @@ DataChannelConnection::HandleSendFailedE
        ssfe->ssfe_info.snd_flags, ssfe->ssfe_error));
   n = ssfe->ssfe_length - sizeof(struct sctp_send_failed_event);
   for (i = 0; i < n; ++i) {
     LOG((" 0x%02x", ssfe->ssfe_data[i]));
   }
 }
 
 void
+DataChannelConnection::ClearResets()
+{
+  // Clear all pending resets
+  if (!mStreamsResetting.IsEmpty()) {
+    LOG(("Clearing resets for %d streams", mStreamsResetting.Length()));
+  }
+
+  for (int32_t i = 0; i < mStreamsResetting.Length(); ++i) {
+    nsRefPtr<DataChannel> channel;
+    channel = FindChannelByStream(mStreamsResetting[i]);
+    if (channel) {
+      LOG(("Forgetting channel %u (%p) with pending reset",channel->mStream, channel.get()));
+      mStreams[channel->mStream] = nullptr;
+    }
+  }
+  mStreamsResetting.Clear();
+}
+
+void
 DataChannelConnection::ResetOutgoingStream(uint16_t streamOut)
 {
   uint32_t i;
 
   mLock.AssertCurrentThreadOwns();
   LOG(("Connection %p: Resetting outgoing stream %u",
        (void *) this, streamOut));
   // Rarely has more than a couple items and only for a short time
@@ -1569,16 +1601,21 @@ DataChannelConnection::SendOutgoingStrea
   memset(srs, 0, len);
   srs->srs_flags = SCTP_STREAM_RESET_OUTGOING;
   srs->srs_number_streams = mStreamsResetting.Length();
   for (i = 0; i < mStreamsResetting.Length(); ++i) {
     srs->srs_stream_list[i] = mStreamsResetting[i];
   }
   if (usrsctp_setsockopt(mMasterSocket, IPPROTO_SCTP, SCTP_RESET_STREAMS, srs, (socklen_t)len) < 0) {
     LOG(("***failed: setsockopt RESET, errno %d", errno));
+    // if errno == EALREADY, this is normal - we can't send another reset
+    // with one pending.
+    // When we get an incoming reset (which may be a response to our
+    // outstanding one), see if we have any pending outgoing resets and
+    // send them
   } else {
     mStreamsResetting.Clear();
   }
   moz_free(srs);
 }
 
 void
 DataChannelConnection::HandleStreamResetEvent(const struct sctp_stream_reset_event *strrst)
@@ -1622,37 +1659,23 @@ DataChannelConnection::HandleStreamReset
           LOG(("Disconnected DataChannel %p from connection %p",
                (void *) channel.get(), (void *) channel->mConnection.get()));
           channel->Destroy();
           // At this point when we leave here, the object is a zombie held alive only by the DOM object
         } else {
           LOG(("Can't find incoming channel %d",i));
         }
       }
-
-      if (strrst->strreset_flags & SCTP_STREAM_RESET_OUTGOING_SSN) {
-        channel = FindChannelByStream(strrst->strreset_stream_list[i]);
-        if (channel) {
-          LOG(("Outgoing: Connection %p channel %p  stream: %u closed",
-               (void *) this, (void *) channel.get(), channel->mStream));
+    }
+  }
 
-          ASSERT_WEBRTC(channel->mState == CLOSING);
-          if (channel->mState == CLOSING) {
-            mStreams[channel->mStream] = nullptr;
-            LOG(("Disconnected DataChannel %p from connection %p (refcnt will be %u)",
-                 (void *) channel.get(), (void *) channel->mConnection.get(),
-                 (uint32_t) channel->mConnection->mRefCnt-1));
-            channel->Destroy();
-            // At this point when we leave here, the object is a zombie held alive only by the DOM object
-          }
-        } else {
-          LOG(("Can't find outgoing channel %d",i));
-        }
-      }
-    }
+  // In case we failed to send a RESET due to having one outstanding, process any pending resets now:
+  if (!mStreamsResetting.IsEmpty()) {
+    LOG(("Sending %d pending resets", mStreamsResetting.Length()));
+    SendOutgoingStreamReset();
   }
 }
 
 void
 DataChannelConnection::HandleStreamChangeEvent(const struct sctp_stream_change_event *strchg)
 {
   uint16_t stream;
   uint32_t i;
@@ -1902,17 +1925,17 @@ DataChannelConnection::OpenFinish(alread
   // Not Open cases are simply queue for non-negotiated, and
   // either change the initial ask or possibly renegotiate after open.
 
   if (mState == OPEN) {
     if (stream == INVALID_STREAM) {
       stream = FindFreeStream(); // may be INVALID_STREAM if we need more
     }
     if (stream == INVALID_STREAM || stream >= mStreams.Length()) {
-      // RequestMoreStreams() limits to MAX_NUM_STREAMS -- allocate extra streams 
+      // RequestMoreStreams() limits to MAX_NUM_STREAMS -- allocate extra streams
       // to avoid going back immediately for more if the ask to N, N+1, etc
       int32_t more_needed = (stream == INVALID_STREAM) ? 16 :
                             (stream-((int32_t)mStreams.Length())) + 16;
       if (!RequestMoreStreams(more_needed)) {
         // Something bad happened... we're done
         goto request_error_cleanup;
       }
       queue = true;
@@ -2227,16 +2250,21 @@ DataChannelConnection::CloseInt(DataChan
   nsRefPtr<DataChannel> channel(aChannel); // make sure it doesn't go away on us
 
   mLock.AssertCurrentThreadOwns();
   LOG(("Connection %p/Channel %p: Closing stream %u",
        channel->mConnection.get(), channel.get(), channel->mStream));
   // re-test since it may have closed before the lock was grabbed
   if (aChannel->mState == CLOSED || aChannel->mState == CLOSING) {
     LOG(("Channel already closing/closed (%u)", aChannel->mState));
+    if (mState == CLOSED && channel->mStream != INVALID_STREAM) {
+      // called from CloseAll()
+      // we're not going to hang around waiting any more
+      mStreams[channel->mStream] = nullptr;
+    }
     return;
   }
   aChannel->mBufferedData.Clear();
   if (channel->mStream != INVALID_STREAM) {
     ResetOutgoingStream(channel->mStream);
     if (mState == CLOSED) { // called from CloseAll()
       // Let resets accumulate then send all at once in CloseAll()
       // we're not going to hang around waiting
@@ -2250,17 +2278,17 @@ DataChannelConnection::CloseInt(DataChan
     // we're not going to hang around waiting
     channel->Destroy();
   }
   // At this point when we leave here, the object is a zombie held alive only by the DOM object
 }
 
 void DataChannelConnection::CloseAll()
 {
-  LOG(("Closing all channels"));
+  LOG(("Closing all channels (connection %p)", (void*) this));
   // Don't need to lock here
 
   // Make sure no more channels will be opened
   {
     MutexAutoLock lock(mLock);
     mState = CLOSED;
   }
 
--- a/netwerk/sctp/datachannel/DataChannel.h
+++ b/netwerk/sctp/datachannel/DataChannel.h
@@ -139,16 +139,19 @@ public:
     virtual void NotifyDataChannel(already_AddRefed<DataChannel> channel) = 0;
   };
 
   DataChannelConnection(DataConnectionListener *listener);
   virtual ~DataChannelConnection();
 
   bool Init(unsigned short aPort, uint16_t aNumStreams, bool aUsingDtls);
   void Destroy(); // So we can spawn refs tied to runnables in shutdown
+  // Finish Destroy on STS to avoid SCTP race condition with ABORT from far end
+  void DestroyOnSTS(struct socket *aMasterSocket,
+                    struct socket *aSocket);
 
 #ifdef ALLOW_DIRECT_SCTP_LISTEN_CONNECT
   // These block; they require something to decide on listener/connector
   // (though you can do simultaneous Connect()).  Do not call these from
   // the main thread!
   bool Listen(unsigned short port);
   bool Connect(const char *addr, unsigned short port);
 #endif
@@ -238,16 +241,17 @@ private:
 
   void DeliverQueuedData(uint16_t stream);
 
   already_AddRefed<DataChannel> OpenFinish(already_AddRefed<DataChannel> channel) NS_WARN_UNUSED_RESULT;
 
   void StartDefer();
   bool SendDeferredMessages();
   void ProcessQueuedOpens();
+  void ClearResets();
   void SendOutgoingStreamReset();
   void ResetOutgoingStream(uint16_t streamOut);
   void HandleOpenRequestMessage(const struct rtcweb_datachannel_open_request *req,
                                 size_t length,
                                 uint16_t streamIn);
   void HandleUnknownMessage(uint32_t ppid, size_t length, uint16_t streamIn);
   void HandleDataMessage(uint32_t ppid, const void *buffer, size_t length, uint16_t streamIn);
   void HandleMessage(const void *buffer, size_t length, uint32_t ppid, uint16_t streamIn);
@@ -519,19 +523,22 @@ public:
               mChannel->mListener->OnChannelConnected(mChannel->mContext);
               break;
             case ON_CHANNEL_CLOSED:
               mChannel->mListener->OnChannelClosed(mChannel->mContext);
               break;
           }
           break;
         }
+      case ON_DISCONNECTED:
+        // If we've disconnected, make sure we close all the streams - from mainthread!
+        mConnection->CloseAll();
+        // fall through
       case ON_CHANNEL_CREATED:
       case ON_CONNECTION:
-      case ON_DISCONNECTED:
         // WeakPtr - only used/modified/nulled from MainThread so we can use a WeakPtr here
         if (!mConnection->mListener) {
           DATACHANNEL_LOG(("DataChannelOnMessageAvailable (%d) with null Listener",mType));
           return NS_OK;
         }
         switch (mType) {
           case ON_CHANNEL_CREATED:
             // important to give it an already_AddRefed pointer!
--- a/netwerk/sctp/src/netinet/sctputil.c
+++ b/netwerk/sctp/src/netinet/sctputil.c
@@ -4737,17 +4737,17 @@ sctp_add_to_readq(struct sctp_inpcb *inp
 			char *buffer;
 			struct sctp_rcvinfo rcv;
 			union sctp_sockstore addr;
 			int flags = 0;
 
 			if ((buffer = malloc(control->length)) == NULL) {
 				return;
 			}
-			so = inp->sctp_socket;
+			so = stcb->sctp_socket;
 			for (m = control->data; m; m = SCTP_BUF_NEXT(m)) {
 				sctp_sbfree(control, control->stcb, &so->so_rcv, m);
 			}
 			atomic_add_int(&stcb->asoc.refcnt, 1);
 			SCTP_TCB_UNLOCK(stcb);
 			m_copydata(control->data, 0, control->length, buffer);
 			memset(&rcv, 0, sizeof(struct sctp_rcvinfo));
 			rcv.rcv_sid = control->sinfo_stream;
--- a/testing/mochitest/tests/SimpleTest/SimpleTest.js
+++ b/testing/mochitest/tests/SimpleTest/SimpleTest.js
@@ -255,16 +255,27 @@ SimpleTest.isnot = function (a, b, name)
  * Roughly equivalent to ok(a===b, name)
 **/
 SimpleTest.ise = function (a, b, name) {
     var pass = (a === b);
     var diag = pass ? "" : "got " + repr(a) + ", strictly expected " + repr(b)
     SimpleTest.ok(pass, name, diag);
 };
 
+/**
+ * Check that the function call throws an exception.
+ */
+SimpleTest.doesThrow = function(fn, name) {
+    var gotException = false;
+    try {
+      fn();
+    } catch (ex) { gotException = true; }
+    ok(gotException, name);
+};
+
 //  --------------- Test.Builder/Test.More todo() -----------------
 
 SimpleTest.todo = function(condition, name, diag) {
     var test = {'result': !!condition, 'name': name, 'diag': diag, todo: true};
     SimpleTest._logResult(test, "TEST-UNEXPECTED-PASS", "TEST-KNOWN-FAIL");
     SimpleTest._tests.push(test);
 };
 
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -226,17 +226,17 @@ nsDownloadManager::RemoveAllDownloads()
 nsresult
 nsDownloadManager::RemoveAllDownloads(nsCOMArray<nsDownload>& aDownloads)
 {
   nsresult rv = NS_OK;
   for (int32_t i = aDownloads.Count() - 1; i >= 0; --i) {
     nsRefPtr<nsDownload> dl = aDownloads[0];
 
     nsresult result = NS_OK;
-    if (dl->IsPaused() && GetQuitBehavior() != QUIT_AND_CANCEL)
+    if (!dl->mPrivate && dl->IsPaused() && GetQuitBehavior() != QUIT_AND_CANCEL)
       aDownloads.RemoveObject(dl);
     else
       result = dl->Cancel();
 
     // Track the failure, but don't miss out on other downloads
     if (NS_FAILED(result))
       rv = result;
   }
@@ -2413,17 +2413,16 @@ nsDownloadManager::Observe(nsISupports *
     if (resumeOnWakeDelay >= 0 && mResumeOnWakeTimer) {
       (void)mResumeOnWakeTimer->InitWithFuncCallback(ResumeOnWakeCallback,
         this, resumeOnWakeDelay, nsITimer::TYPE_ONE_SHOT);
     }
   } else if (strcmp(aTopic, "last-pb-context-exited") == 0) {
     // Upon leaving private browsing mode, cancel all private downloads,
     // remove all trace of them, and then blow away the private database
     // and recreate a blank one.
-    PauseAllDownloads(mCurrentPrivateDownloads, true);
     RemoveAllDownloads(mCurrentPrivateDownloads);
     InitPrivateDB();
   } else if (strcmp(aTopic, "last-pb-context-exiting") == 0) {
     // If there are active private downloads, prompt the user to confirm leaving
     // private browsing mode (thereby cancelling them). Otherwise, silently proceed.
     if (!mCurrentPrivateDownloads.Count())
       return NS_OK;
 
--- a/toolkit/components/downloads/test/unit/test_privatebrowsing_cancel.js
+++ b/toolkit/components/downloads/test/unit/test_privatebrowsing_cancel.js
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
   Make sure that the download manager service is given a chance to cancel the
-  private browisng mode transition.
+  private browsing mode transition.
 **/
 
 const Cm = Components.manager;
 
 const kPromptServiceUUID = "{6cc9c9fe-bc0b-432b-a410-253ef8bcc699}";
 const kPromptServiceContractID = "@mozilla.org/embedcomp/prompt-service;1";
 
 // Save original prompt service factory
@@ -73,19 +73,19 @@ function trigger_pb_cleanup(expected)
   obs.notifyObservers(cancel, "last-pb-context-exiting", null);
   do_check_eq(expected, cancel.data);
   if (!expected)
     obs.notifyObservers(cancel, "last-pb-context-exited", null);
 }
 
 function run_test() {
   function finishTest() {
-    // Cancel Download-E
-    dlF.cancel();
-    dlF.remove();
+    // Cancel Download-G
+    dlG.cancel();
+    dlG.remove();
     dm.cleanUp();
     dm.cleanUpPrivate();
     do_check_eq(dm.activeDownloadCount, 0);
     do_check_eq(dm.activePrivateDownloadCount, 0);
 
     dm.removeListener(listener);
     httpserv.stop(do_test_finished);
 
@@ -156,39 +156,64 @@ function run_test() {
             trigger_pb_cleanup(true);
             do_check_true(promptService.wasCalled());
             do_check_eq(dm.activePrivateDownloadCount, 1);
 
             promptService.sayProceed();
             trigger_pb_cleanup(false);
             do_check_true(promptService.wasCalled());
             do_check_eq(dm.activePrivateDownloadCount, 0);
-            do_check_eq(dlE.state, dm.DOWNLOAD_PAUSED);
+            do_check_eq(dlE.state, dm.DOWNLOAD_CANCELED);
 
             // Create Download-F
             dlF = addDownload({
-              isPrivate: false,
+              isPrivate: true,
               targetFile: fileF,
               sourceURI: downloadFSource,
               downloadName: downloadFName
             });
 
             // Wait for Download-F to start
           } else if (aDownload.targetFile.equals(dlF.targetFile)) {
-            // Sanity check: Download-F must not be resumable
-            do_check_false(dlF.resumable);
+            // Sanity check: Download-F must be resumable
+            do_check_true(dlF.resumable);
+            dlF.pause();
+
+          } else if (aDownload.targetFile.equals(dlG.targetFile)) {
+            // Sanity check: Download-G must not be resumable
+            do_check_false(dlG.resumable);
 
             promptService.sayCancel();
             trigger_pb_cleanup(false);
             do_check_false(promptService.wasCalled());
             do_check_eq(dm.activeDownloadCount, 1);
-            do_check_eq(dlF.state, dm.DOWNLOAD_DOWNLOADING);
+            do_check_eq(dlG.state, dm.DOWNLOAD_DOWNLOADING);
             finishTest();
           }
           break;
+
+        case dm.DOWNLOAD_PAUSED:
+          if (aDownload.targetFile.equals(dlF.targetFile)) {
+            promptService.sayProceed();
+            trigger_pb_cleanup(false);
+            do_check_true(promptService.wasCalled());
+            do_check_eq(dm.activePrivateDownloadCount, 0);
+            do_check_eq(dlF.state, dm.DOWNLOAD_CANCELED);
+
+            // Create Download-G
+            dlG = addDownload({
+              isPrivate: false,
+              targetFile: fileG,
+              sourceURI: downloadGSource,
+              downloadName: downloadGName
+            });
+
+            // Wait for Download-G to start
+          }
+          break;
       }
     },
     onStateChange: function(a, b, c, d, e) { },
     onProgressChange: function(a, b, c, d, e, f, g) { },
     onSecurityChange: function(a, b, c, d) { }
   };
 
   dm.addPrivacyAwareListener(listener);
@@ -199,35 +224,43 @@ function run_test() {
   const downloadDName = "download-D";
 
   // properties of Download-E
   const downloadESource = "http://localhost:4444/file/head_download_manager.js";
   const downloadEDest = "download-file-E";
   const downloadEName = "download-E";
 
   // properties of Download-F
-  const downloadFSource = "http://localhost:4444/noresume";
+  const downloadFSource = "http://localhost:4444/file/head_download_manager.js";
   const downloadFDest = "download-file-F";
   const downloadFName = "download-F";
 
+  // properties of Download-G
+  const downloadGSource = "http://localhost:4444/noresume";
+  const downloadGDest = "download-file-G";
+  const downloadGName = "download-G";
+
   // Create all target files
   let fileD = tmpDir.clone();
   fileD.append(downloadDDest);
   fileD.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
   let fileE = tmpDir.clone();
   fileE.append(downloadEDest);
   fileE.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
   let fileF = tmpDir.clone();
   fileF.append(downloadFDest);
   fileF.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+  let fileG = tmpDir.clone();
+  fileG.append(downloadGDest);
+  fileG.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
 
   // Create Download-D
   let dlD = addDownload({
     isPrivate: true,
     targetFile: fileD,
     sourceURI: downloadDSource,
     downloadName: downloadDName
   });
 
-  let dlE, dlF;
+  let dlE, dlF, dlG;
 
   // wait for Download-D to start
 }
--- a/toolkit/components/social/SocialService.jsm
+++ b/toolkit/components/social/SocialService.jsm
@@ -729,22 +729,23 @@ SocialProvider.prototype = {
   _pageMarkInfo: null,
   get pageMarkInfo() {
     return this._pageMarkInfo;
   },
   set pageMarkInfo(data) {
     // Accept *and validate* the page-mark-config message from the provider.
     let promptImages = {};
     let promptMessages = {};
+    let self = this;
     function reportError(reason) {
       Cu.reportError("Invalid page-mark data from provider: " + reason + ": marking is disabled for this provider");
       // and we explicitly reset the page-mark data to null to avoid stale
       // data being used and notify our observers.
-      this._pageMarkInfo = null;
-      Services.obs.notifyObservers(null, "social:page-mark-config", this.origin);
+      self._pageMarkInfo = null;
+      Services.obs.notifyObservers(null, "social:page-mark-config", self.origin);
     }
     if (!data ||
         !data.images || typeof data.images != "object" ||
         !data.messages || typeof data.messages != "object") {
       reportError("data is missing valid 'images' or 'messages' elements");
       return;
     }
     for (let sub of ["marked", "unmarked"]) {
--- a/toolkit/components/social/WorkerAPI.jsm
+++ b/toolkit/components/social/WorkerAPI.jsm
@@ -73,17 +73,17 @@ WorkerAPI.prototype = {
         let [name, value] = aCookie.split("=");
         results.push({name: unescape(name.trim()),
                       value: value ? unescape(value.trim()) : ""});
       });
       this._port.postMessage({topic: "social.cookies-get-response",
                               data: results});
     },
     'social.request-chat': function(data) {
-      openChatWindow(null, this._provider, data, null, "minimized");
+      openChatWindow(null, this._provider, data);
     },
     'social.notification-create': function(data) {
       if (!Services.prefs.getBoolPref("social.toast-notifications.enabled"))
         return;
 
       let port = this._port;
       let provider = this._provider;
       let {id, type, icon, body, action, actionArgs} = data;
--- a/toolkit/components/thumbnails/test/browser_thumbnails_background.js
+++ b/toolkit/components/thumbnails/test/browser_thumbnails_background.js
@@ -189,16 +189,53 @@ let tests = [
     let win = yield openPrivateWindow();
     let capturedURL = yield capture(url);
     is(capturedURL, url, "Captured URL should be URL passed to capture.");
     ok(!file.exists(),
        "Thumbnail file should not exist because a private window is open.");
 
     win.close();
   },
+
+  function noCookies() {
+    // Visit the test page in the browser and tell it to set a cookie.
+    let url = testPageURL({ setGreenCookie: true });
+    let tab = gBrowser.loadOneTab(url, { inBackground: false });
+    let browser = tab.linkedBrowser;
+    yield onPageLoad(browser);
+
+    // The root element of the page shouldn't be green yet.
+    let greenStr = "rgb(0, 255, 0)";
+    isnot(browser.contentDocument.documentElement.style.backgroundColor,
+          greenStr,
+          "The page shouldn't be green yet.");
+
+    // Cookie should be set now.  Reload the page to verify.  Its root element
+    // will be green if the cookie's set.
+    browser.reload();
+    yield onPageLoad(browser);
+    is(browser.contentDocument.documentElement.style.backgroundColor,
+       greenStr,
+       "The page should be green now.");
+
+    // Capture the page.  Get the image data of the capture and verify it's not
+    // green.  (Checking only the first pixel suffices.)
+    yield capture(url);
+    let file = fileForURL(url);
+    ok(file.exists(), "Thumbnail file should exist after capture.");
+
+    let deferred = imports.Promise.defer();
+    retrieveImageDataForURL(url, function ([r, g, b]) {
+      isnot([r, g, b].toString(), [0, 255, 0].toString(),
+            "The captured page should not be green.");
+      gBrowser.removeTab(tab);
+      deferred.resolve();
+    });
+    yield deferred.promise;
+  },
 ];
 
 function capture(url, options) {
   let deferred = imports.Promise.defer();
   options = options || {};
   options.onDone = function onDone(capturedURL) {
     deferred.resolve(capturedURL);
   };
@@ -234,8 +271,19 @@ function openPrivateWindow() {
   win.addEventListener("load", function load(event) {
     if (event.target == win.document) {
       win.removeEventListener("load", load);
       deferred.resolve(win);
     }
   });
   return deferred.promise;
 }
+
+function onPageLoad(browser) {
+  let deferred = imports.Promise.defer();
+  browser.addEventListener("load", function load(event) {
+    if (event.target == browser.contentWindow.document) {
+      browser.removeEventListener("load", load, true);
+      deferred.resolve();
+    }
+  }, true);
+  return deferred.promise;
+}
--- a/toolkit/components/thumbnails/test/thumbnails_background.sjs
+++ b/toolkit/components/thumbnails/test/thumbnails_background.sjs
@@ -12,16 +12,26 @@ function handleRequest(req, resp) {
   resp.setHeader("Content-Type", "text/html;charset=utf-8", false);
 
   let opts = {};
   try {
     opts = JSON.parse(decodeURIComponent(req.queryString));
   }
   catch (err) {}
 
+  if (opts.setGreenCookie)
+    resp.setHeader("Set-Cookie", "green", false);
+
+  if (req.hasHeader("Cookie") &&
+      req.getHeader("Cookie").split(";").indexOf("green") >= 0) {
+    resp.write('<html style="background: #0f0;"></html>');
+    resp.finish();
+    return;
+  }
+
   if (opts.redirect) {
     resp.setHeader("Location", opts.redirect);
     resp.setStatusLine(null, 303, null);
     resp.finish();
     return;
   }
 
   if (opts.wait) {
--- a/toolkit/mozapps/extensions/PluginProvider.jsm
+++ b/toolkit/mozapps/extensions/PluginProvider.jsm
@@ -397,19 +397,29 @@ function PluginWrapper(aId, aName, aDesc
     let paths = [];
     for (let tag of aTags)
       paths.push(tag.fullpath);
     return paths;
   })
 
   this.__defineGetter__("pluginMimeTypes", function() {
     let types = [];
-    for (let tag of aTags)
-      for (let type of tag.getMimeTypes({}))
+    for (let tag of aTags) {
+      let mimeTypes = tag.getMimeTypes({});
+      let mimeDescriptions = tag.getMimeDescriptions({});
+      let extensions = tag.getExtensions({});
+      for (let i = 0; i < mimeTypes.length; i++) {
+        let type = {};
+        type.type = mimeTypes[i];
+        type.description = mimeDescriptions[i];
+        type.suffixes = extensions[i];
+
         types.push(type);
+      }
+    }
     return types;
   });
 
   this.__defineGetter__("installDate", function() {
     let date = 0;
     let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
     for (let tag of aTags) {
       file.initWithPath(tag.fullpath);
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -277,16 +277,41 @@ SetTaskbarGroupId(const nsString& aId)
 nsresult
 XRE_InitChildProcess(int aArgc,
                      char* aArgv[],
                      GeckoProcessType aProcess)
 {
   NS_ENSURE_ARG_MIN(aArgc, 2);
   NS_ENSURE_ARG_POINTER(aArgv);
   NS_ENSURE_ARG_POINTER(aArgv[0]);
+
+#if defined(XP_WIN)
+  // From the --attach-console support in nsNativeAppSupportWin.cpp, but
+  // here we are a content child process, so we always attempt to attach
+  // to the parent's (ie, the browser's) console.
+  // Try to attach console to the parent process.
+  // It will succeed when the parent process is a command line,
+  // so that stdio will be displayed in it.
+  if (AttachConsole(ATTACH_PARENT_PROCESS)) {
+    // Change std handles to refer to new console handles.
+    // Before doing so, ensure that stdout/stderr haven't been
+    // redirected to a valid file
+    if (_fileno(stdout) == -1 ||
+        _get_osfhandle(fileno(stdout)) == -1)
+        freopen("CONOUT$", "w", stdout);
+    // Merge stderr into CONOUT$ since there isn't any `CONERR$`.
+    // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
+    if (_fileno(stderr) == -1 ||
+        _get_osfhandle(fileno(stderr)) == -1)
+        freopen("CONOUT$", "w", stderr);
+    if (_fileno(stdin) == -1 || _get_osfhandle(fileno(stdin)) == -1)
+        freopen("CONIN$", "r", stdin);
+  }
+#endif
+
   char aLocal;
   profiler_init(&aLocal);
   PROFILER_LABEL("Startup", "XRE_InitChildProcess");
 
   sChildProcessType = aProcess;
 
   // Complete 'task_t' exchange for Mac OS X. This structure has the same size
   // regardless of architecture so we don't have any cross-arch issues here.
--- a/xpcom/ds/TimeStamp.h
+++ b/xpcom/ds/TimeStamp.h
@@ -202,17 +202,17 @@ private:
  * t.IsNull() is equivalent to t.time_since_epoch() == decltype(t)::duration::zero();
  */
 class TimeStamp
 {
 public:
   /**
    * Initialize to the "null" moment
    */
-  TimeStamp() : mValue(0) {}
+  MOZ_CONSTEXPR TimeStamp() : mValue(0) {}
   // Default copy-constructor and assignment are OK
 
   /**
    * Return true if this is the "null" moment
    */
   bool IsNull() const { return mValue == 0; }
   /**
    * Return a timestamp reflecting the current elapsed system time. This
--- a/xpcom/ds/TimeStamp_windows.cpp
+++ b/xpcom/ds/TimeStamp_windows.cpp
@@ -317,23 +317,22 @@ InitResolution()
 
   sResolutionSigDigs = sigDigs;
 }
 
 // ----------------------------------------------------------------------------
 // TimeStampValue implementation
 // ----------------------------------------------------------------------------
 
-TimeStampValue::TimeStampValue(_SomethingVeryRandomHere* nullValue)
+MOZ_CONSTEXPR TimeStampValue::TimeStampValue(_SomethingVeryRandomHere* nullValue)
   : mGTC(0)
   , mQPC(0)
   , mHasQPC(false)
   , mIsNull(true)
 {
-  MOZ_ASSERT(!nullValue);
 }
 
 TimeStampValue::TimeStampValue(ULONGLONG aGTC, ULONGLONG aQPC, bool aHasQPC)
   : mGTC(aGTC)
   , mQPC(aQPC)
   , mHasQPC(aHasQPC)
   , mIsNull(false)
 {
--- a/xpcom/ds/TimeStamp_windows.h
+++ b/xpcom/ds/TimeStamp_windows.h
@@ -22,20 +22,20 @@ class TimeStampValue
   uint64_t mQPC;
   bool mHasQPC;
   bool mIsNull;
 
   TimeStampValue(uint64_t GTC, uint64_t QPC, bool hasQPC);
 
   uint64_t CheckQPC(const TimeStampValue &aOther) const;
 
+  struct _SomethingVeryRandomHere;
+  MOZ_CONSTEXPR TimeStampValue(_SomethingVeryRandomHere* nullValue);
+
 public:
-  struct _SomethingVeryRandomHere;
-  TimeStampValue(_SomethingVeryRandomHere* nullValue);
-
   uint64_t operator-(const TimeStampValue &aOther) const;
 
   TimeStampValue operator+(const int64_t aOther) const
     { return TimeStampValue(mGTC + aOther, mQPC + aOther, mHasQPC); }
   TimeStampValue operator-(const int64_t aOther) const
     { return TimeStampValue(mGTC - aOther, mQPC - aOther, mHasQPC); }
   TimeStampValue& operator+=(const int64_t aOther);
   TimeStampValue& operator-=(const int64_t aOther);
--- a/xpcom/reflect/xptcall/src/md/unix/moz.build
+++ b/xpcom/reflect/xptcall/src/md/unix/moz.build
@@ -15,17 +15,17 @@ if CONFIG['OS_ARCH'] == 'Darwin':
             ]
         else:
             CPP_SOURCES += [
                 'xptcinvoke_gcc_x86_unix.cpp',
                 'xptcstubs_gcc_x86_unix.cpp',
             ]
 
 if CONFIG['OS_ARCH'] in ('NetBSD', 'OpenBSD', 'GNU'):
-    if CONFIG['OS_TEST'].find('86') != -1:
+    if CONFIG['CPU_ARCH'] == 'x86':
         CPP_SOURCES += [
             'xptcinvoke_gcc_x86_unix.cpp',
             'xptcstubs_gcc_x86_unix.cpp'
         ]
 
 if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD') or \
    CONFIG['OS_ARCH'].startswith('GNU_'):
     if CONFIG['OS_TEST'] == 'x86_64':
--- a/xpfe/appshell/src/nsXULWindow.cpp
+++ b/xpfe/appshell/src/nsXULWindow.cpp
@@ -20,17 +20,16 @@
 #include "nsNetCID.h"
 
 //Interfaces needed to be included
 #include "nsIAppShell.h"
 #include "nsIAppShellService.h"
 #include "nsIServiceManager.h"
 #include "nsIContentViewer.h"
 #include "nsIDocument.h"
-#include "nsIDOMBarProp.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMScreen.h"
 #include "nsIEmbeddingSiteWindow.h"
 #include "nsIInterfaceRequestor.h"
@@ -49,19 +48,21 @@
 #include "nsAppShellCID.h"
 #include "nsReadableUtils.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 #include "nsWebShellWindow.h" // get rid of this one, too...
 #include "nsDOMEvent.h"
+#include "nsGlobalWindow.h"
 
 #include "prenv.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/dom/BarProps.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 
 #define SIZEMODE_NORMAL     NS_LITERAL_STRING("normal")
 #define SIZEMODE_MAXIMIZED  NS_LITERAL_STRING("maximized")
 #define SIZEMODE_MINIMIZED  NS_LITERAL_STRING("minimized")
 #define SIZEMODE_FULLSCREEN NS_LITERAL_STRING("fullscreen")
@@ -1976,22 +1977,24 @@ void nsXULWindow::PlaceWindowLayersBehin
         nextWidget->PlaceBehind(eZPlacementBelow, previousHighWidget, false);
       previousHighWidget = nextWidget;
     }
   }
 }
 
 void nsXULWindow::SetContentScrollbarVisibility(bool aVisible)
 {
-  nsCOMPtr<nsIDOMWindow> contentWin(do_GetInterface(mPrimaryContentShell));
+  nsCOMPtr<nsPIDOMWindow> contentWin(do_GetInterface(mPrimaryContentShell));
   if (contentWin) {
-    nsCOMPtr<nsIDOMBarProp> scrollbars;
-    contentWin->GetScrollbars(getter_AddRefs(scrollbars));
-    if (scrollbars)
-      scrollbars->SetVisible(aVisible);
+    nsRefPtr<nsGlobalWindow> window = static_cast<nsGlobalWindow*>(contentWin.get());
+    nsRefPtr<mozilla::dom::BarProp> scrollbars = window->Scrollbars();
+    if (scrollbars) {
+      mozilla::ErrorResult rv;
+      scrollbars->SetVisible(aVisible, rv);
+    }
   }
 }
 
 bool nsXULWindow::GetContentScrollbarVisibility()
 {
   // This code already exists in dom/src/base/nsBarProp.cpp, but we
   // can't safely get to that from here as this function is called
   // while the DOM window is being set up, and we need the DOM window