Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 06 Feb 2013 16:55:25 -0500
changeset 130906 325397090d125787c40469b625b9edbefacef44f
parent 130866 beca57e612fd8a3da02b1e54509c192e63b24451 (current diff)
parent 130905 b04245038b278c2bfff34a62c41c36908a84f519 (diff)
child 130939 fbcbc4ff374768f1dfa1928a06e004c9b8624177
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone21.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 the last PGO-green inbound changeset to m-c.
dom/interfaces/html/nsIUndoManagerTransaction.idl
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -3075,17 +3075,17 @@ Accessible::GetFirstAvailableAccessible(
   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aStartNode->OwnerDoc());
   NS_ENSURE_TRUE(domDoc, nullptr);
 
   nsCOMPtr<nsIDOMNode> currentNode = do_QueryInterface(aStartNode);
   nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(GetNode());
   nsCOMPtr<nsIDOMTreeWalker> walker;
   domDoc->CreateTreeWalker(rootNode,
                            nsIDOMNodeFilter::SHOW_ELEMENT | nsIDOMNodeFilter::SHOW_TEXT,
-                           nullptr, false, getter_AddRefs(walker));
+                           nullptr, 1, getter_AddRefs(walker));
   NS_ENSURE_TRUE(walker, nullptr);
 
   walker->SetCurrentNode(currentNode);
   while (true) {
     walker->NextNode(getter_AddRefs(currentNode));
     if (!currentNode)
       return nullptr;
 
--- a/accessible/tests/mochitest/name/markup.js
+++ b/accessible/tests/mochitest/name/markup.js
@@ -266,17 +266,17 @@ function testNameForElmRule(aElm, aRule)
 
       mLocalName: tagname,
       mAttrName: attrname,
       mAttrValue: aElm.getAttribute("id")
     };
 
     var treeWalker = document.createTreeWalker(document.body,
                                                NodeFilter.SHOW_ELEMENT,
-                                               filter, false);
+                                               filter);
     labelElm = treeWalker.nextNode();
 
   } else {
     // if attrname is empty then look for the element in subtree.
     labelElm = aElm.getElementsByTagName(tagname)[0];
     if (!labelElm)
       labelElm = aElm.getElementsByTagName("html:" + tagname)[0];
   }
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -64,16 +64,22 @@ XPCOMUtils.defineLazyGetter(this, "ppmm"
 
 #ifdef MOZ_WIDGET_GONK
 XPCOMUtils.defineLazyGetter(this, "libcutils", function () {
   Cu.import("resource://gre/modules/systemlibs.js");
   return libcutils;
 });
 #endif
 
+#ifdef MOZ_SERVICES_CAPTIVEDETECT
+XPCOMUtils.defineLazyServiceGetter(Services, 'captivePortalDetector',
+                                  '@mozilla.org/services/captive-detector;1',
+                                  'nsICaptivePortalDetector');
+#endif
+
 function getContentWindow() {
   return shell.contentBrowser.contentWindow;
 }
 
 function debug(str) {
   dump(' -*- Shell.js: ' + str + '\n');
 }
 
@@ -279,16 +285,17 @@ var shell = {
     window.addEventListener('sizemodechange', this);
     this.contentBrowser.addEventListener('mozbrowserloadstart', this, true);
 
     CustomEventManager.init();
     WebappsHelper.init();
     AccessFu.attach(window);
     UserAgentOverrides.init();
     IndexedDBPromptHelper.init();
+    CaptivePortalLoginHelper.init();
 
     // XXX could factor out into a settings->pref map.  Not worth it yet.
     SettingsListener.observe("debug.fps.enabled", false, function(value) {
       Services.prefs.setBoolPref("layers.acceleration.draw-fps", value);
     });
     SettingsListener.observe("debug.paint-flashing.enabled", false, function(value) {
       Services.prefs.setBoolPref("nglayout.debug.paint_flashing", value);
     });
@@ -640,16 +647,19 @@ var CustomEventManager = {
         FormsHelper.handleEvent(detail);
         break;
       case 'system-message-listener-ready':
         Services.obs.notifyObservers(null, 'system-message-listener-ready', null);
         break;
       case 'remote-debugger-prompt':
         RemoteDebugger.handleEvent(detail);
         break;
+      case 'captive-portal-login-cancel':
+        CaptivePortalLoginHelper.handleEvent(detail);
+        break;
     }
   }
 }
 
 var AlertsHelper = {
   _listeners: {},
   _count: 0,
 
@@ -990,16 +1000,29 @@ window.addEventListener('ContentStart', 
       let props = aSubject.QueryInterface(Ci.nsIPropertyBag2);
       if (props.hasKey("abnormal") && props.hasKey("dumpID")) {
         shell.reportCrash(false, props.getProperty("dumpID"));
       }
     },
     "ipc:content-shutdown", false);
 })();
 
+var CaptivePortalLoginHelper = {
+  init: function init() {
+    Services.obs.addObserver(this, 'captive-portal-login', false);
+    Services.obs.addObserver(this, 'captive-portal-login-abort', false);
+  },
+  handleEvent: function handleEvent(detail) {
+    Services.captivePortalDetector.cancelLogin(detail.id);
+  },
+  observe: function observe(subject, topic, data) {
+    shell.sendChromeEvent(JSON.parse(data));
+  }
+}
+
 // Listen for crashes submitted through the crash reporter UI.
 window.addEventListener('ContentStart', function cr_onContentStart() {
   let content = shell.contentBrowser.contentWindow;
   content.addEventListener("mozContentEvent", function cr_onMozContentEvent(e) {
     if (e.detail.type == "submit-crash" && e.detail.crashID) {
       shell.submitCrash(e.detail.crashID);
     }
   });
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -15,16 +15,17 @@ MOZ_B2G_OS_NAME=Boot2Gecko
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=
 MOZ_SERVICES_COMMON=1
 MOZ_SERVICES_METRICS=1
+MOZ_SERVICES_CAPTIVEDETECT=1
 
 MOZ_WEBSMS_BACKEND=1
 MOZ_DISABLE_DOMCRYPTO=1
 MOZ_APP_STATIC_INI=1
 
 if test "$OS_TARGET" = "Android"; then
 MOZ_CAPTURE=1
 MOZ_RAW=1
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -282,16 +282,19 @@
 @BINPATH@/components/rdf.xpt
 @BINPATH@/components/satchel.xpt
 @BINPATH@/components/saxparser.xpt
 @BINPATH@/components/sessionstore.xpt
 #ifdef MOZ_SERVICES_SYNC
 @BINPATH@/components/services-crypto.xpt
 #endif
 @BINPATH@/components/services-crypto-component.xpt
+#ifdef MOZ_SERVICES_CAPTIVEDETECT
+@BINPATH@/components/services-captivedetect.xpt
+#endif
 @BINPATH@/components/shellservice.xpt
 @BINPATH@/components/shistory.xpt
 @BINPATH@/components/spellchecker.xpt
 @BINPATH@/components/storage.xpt
 @BINPATH@/components/telemetry.xpt
 @BINPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @BINPATH@/components/toolkitremote.xpt
@@ -488,16 +491,20 @@
 @BINPATH@/components/WeaveCrypto.js
 #endif
 @BINPATH@/components/servicesComponents.manifest
 @BINPATH@/components/cryptoComponents.manifest
 #ifdef MOZ_SERVICES_HEALTHREPORT
 @BINPATH@/components/HealthReportComponents.manifest
 @BINPATH@/components/HealthReportService.js
 #endif
+#ifdef MOZ_SERVICES_CAPTIVEDETECT
+@BINPATH@/components/CaptivePortalDetectComponents.manifest
+@BINPATH@/components/captivedetect.js
+#endif
 @BINPATH@/components/TelemetryPing.js
 @BINPATH@/components/TelemetryPing.manifest
 @BINPATH@/components/Webapps.js
 @BINPATH@/components/Webapps.manifest
 @BINPATH@/components/AppsService.js
 @BINPATH@/components/AppsService.manifest
 
 @BINPATH@/components/nsDOMIdentity.js
@@ -585,16 +592,19 @@
 @BINPATH@/defaults/autoconfig/platform.js
 @BINPATH@/defaults/autoconfig/prefcalls.js
 @BINPATH@/defaults/profile/prefs.js
 
 ; Services (gre) prefs
 #ifdef MOZ_SERVICES_SYNC
 @BINPATH@/defaults/pref/services-sync.js
 #endif
+#ifdef MOZ_SERVICES_CAPTIVEDETECT
+@BINPATH@/defaults/pref/services-captivedetect.js
+#endif
 
 ; [Layout Engine Resources]
 ; Style Sheets, Graphics and other Resources used by the layout engine. 
 @BINPATH@/res/EditorOverride.css
 @BINPATH@/res/contenteditable.css
 @BINPATH@/res/designmode.css
 @BINPATH@/res/table-add-column-after-active.gif
 @BINPATH@/res/table-add-column-after-hover.gif
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -570,17 +570,17 @@ function goThroughFrames(aDocument, aWin
   }
 }
 
 function processFrames()
 {
   if (gFrameList.length) {
     var doc = gFrameList[0];
     onProcessFrame.forEach(function(func) { func(doc); });
-    var iterator = doc.createTreeWalker(doc, NodeFilter.SHOW_ELEMENT, grabAll, true);
+    var iterator = doc.createTreeWalker(doc, NodeFilter.SHOW_ELEMENT, grabAll);
     gFrameList.shift();
     setTimeout(doGrab, 10, iterator);
     onFinished.push(selectImage);
   }
   else
     onFinished.forEach(function(func) { func(); });
 }
 
--- a/browser/components/privatebrowsing/test/browser/perwindow/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/perwindow/Makefile.in
@@ -10,19 +10,16 @@ relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_BROWSER_FILES =  \
 		head.js \
 		browser_privatebrowsing_certexceptionsui.js \
 		browser_privatebrowsing_concurrent.js \
 		browser_privatebrowsing_concurrent_page.html \
-		browser_privatebrowsing_cookieacceptdialog.js \
-		browser_privatebrowsing_cookieacceptdialog.html \
-		browser_privatebrowsing_crh.js \
 		browser_privatebrowsing_downloadLastDir.js \
 		browser_privatebrowsing_downloadLastDir_c.js \
 		browser_privatebrowsing_downloadLastDir_toggle.js \
 		browser_privatebrowsing_DownloadLastDirWithCPS.js \
 		browser_privatebrowsing_geoprompt.js \
 		browser_privatebrowsing_geoprompt_page.html \
 		browser_privatebrowsing_lastpbcontextexited.js \
 		browser_privatebrowsing_localStorage.js \
@@ -47,9 +44,18 @@ MOCHITEST_BROWSER_FILES =  \
 		browser_privatebrowsing_windowtitle.js \
 		browser_privatebrowsing_windowtitle_page.html \
 		browser_privatebrowsing_zoom.js \
 		browser_privatebrowsing_zoomrestore.js \
 		popup.html \
 		title.sjs \
 		$(NULL)
 
+# Temporarily disabled on OS X for bug 822284
+ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
+MOCHITEST_BROWSER_FILES += \
+		browser_privatebrowsing_cookieacceptdialog.js \
+		browser_privatebrowsing_cookieacceptdialog.html \
+		browser_privatebrowsing_crh.js \
+		$(NULL)
+endif
+
 include $(topsrcdir)/config/rules.mk
--- a/browser/devtools/markupview/MarkupView.jsm
+++ b/browser/devtools/markupview/MarkupView.jsm
@@ -116,18 +116,17 @@ MarkupView.prototype = {
     let walker = this.doc.createTreeWalker(
       aStart || this._elt,
       Ci.nsIDOMNodeFilter.SHOW_ELEMENT,
       function(aElement) {
         if (aElement.container && aElement.container.visible) {
           return Ci.nsIDOMNodeFilter.FILTER_ACCEPT;
         }
         return Ci.nsIDOMNodeFilter.FILTER_SKIP;
-      },
-      false
+      }
     );
     walker.currentNode = this._selectedContainer.elt;
     return walker;
   },
 
   /**
    * Key handling.
    */
@@ -1311,34 +1310,33 @@ ElementEditor.prototype = {
 
 RootContainer.prototype = {
   hasChildren: true,
   expanded: true,
   update: function RC_update() {}
 };
 
 function documentWalker(node) {
-  return new DocumentWalker(node, Ci.nsIDOMNodeFilter.SHOW_ALL, whitespaceTextFilter, false);
+  return new DocumentWalker(node, Ci.nsIDOMNodeFilter.SHOW_ALL, whitespaceTextFilter);
 }
 
 function nodeDocument(node) {
   return node.ownerDocument || (node.nodeType == Ci.nsIDOMNode.DOCUMENT_NODE ? node : null);
 }
 
 /**
  * Similar to a TreeWalker, except will dig in to iframes and it doesn't
  * implement the good methods like previousNode and nextNode.
  *
  * See TreeWalker documentation for explanations of the methods.
  */
-function DocumentWalker(aNode, aShow, aFilter, aExpandEntityReferences)
+function DocumentWalker(aNode, aShow, aFilter)
 {
   let doc = nodeDocument(aNode);
-  this.walker = doc.createTreeWalker(nodeDocument(aNode),
-    aShow, aFilter, aExpandEntityReferences);
+  this.walker = doc.createTreeWalker(nodeDocument(aNode), aShow, aFilter);
   this.walker.currentNode = aNode;
   this.filter = aFilter;
 }
 
 DocumentWalker.prototype = {
   get node() this.walker.node,
   get whatToShow() this.walker.whatToShow,
   get expandEntityReferences() this.walker.expandEntityReferences,
--- a/browser/devtools/markupview/test/browser_inspector_markup_mutation.js
+++ b/browser/devtools/markupview/test/browser_inspector_markup_mutation.js
@@ -26,17 +26,17 @@ function test() {
 
   let inspector;
 
   // Strip whitespace from a node and its children.
   function stripWhitespace(node)
   {
     node.normalize();
     let iter = node.ownerDocument.createNodeIterator(node, NodeFilter.SHOW_TEXT + NodeFilter.SHOW_COMMENT,
-      null, false);
+      null);
 
     while ((node = iter.nextNode())) {
       node.nodeValue = node.nodeValue.replace(/\s+/g, '');
       if (node.nodeType == Node.TEXT_NODE &&
         !/[^\s]/.exec(node.nodeValue)) {
         node.parentNode.removeChild(node);
       }
     }
--- a/browser/devtools/shared/DOMHelpers.jsm
+++ b/browser/devtools/shared/DOMHelpers.jsm
@@ -91,17 +91,17 @@ DOMHelpers.prototype = {
 
     return null;  // we have no children worth showing.
   },
 
   getFirstChild: function Helpers_getFirstChild(node)
   {
     let SHOW_ALL = Components.interfaces.nsIDOMNodeFilter.SHOW_ALL;
     this.treeWalker = node.ownerDocument.createTreeWalker(node,
-      SHOW_ALL, null, false);
+      SHOW_ALL, null);
     return this.treeWalker.firstChild();
   },
 
   getNextSibling: function Helpers_getNextSibling(node)
   {
     let next = this.treeWalker.nextSibling();
 
     if (!next)
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -279,16 +279,19 @@
 #ifdef MOZ_ENABLE_PROFILER_SPS
 @BINPATH@/components/profiler.xpt
 #endif
 @BINPATH@/components/rdf.xpt
 @BINPATH@/components/satchel.xpt
 @BINPATH@/components/saxparser.xpt
 @BINPATH@/components/sessionstore.xpt
 @BINPATH@/components/services-crypto-component.xpt
+#ifdef MOZ_SERVICES_CAPTIVEDETECT
+@BINPATH@/components/services-captivedetect.xpt
+#endif
 @BINPATH@/components/shellservice.xpt
 @BINPATH@/components/shistory.xpt
 @BINPATH@/components/spellchecker.xpt
 @BINPATH@/components/storage.xpt
 @BINPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @BINPATH@/components/toolkitremote.xpt
 #endif
@@ -468,16 +471,20 @@
 #endif
 #ifdef MOZ_SERVICES_HEALTHREPORT
 @BINPATH@/components/HealthReportComponents.manifest
 #endif
 #ifdef MOZ_SERVICES_SYNC
 @BINPATH@/components/SyncComponents.manifest
 @BINPATH@/components/Weave.js
 #endif
+#ifdef MOZ_SERVICES_CAPTIVEDETECT
+@BINPATH@/components/CaptivePortalDetectComponents.manifest
+@BINPATH@/components/captivedetect.js
+#endif
 @BINPATH@/components/servicesComponents.manifest
 @BINPATH@/components/cryptoComponents.manifest
 @BINPATH@/components/TelemetryPing.js
 @BINPATH@/components/TelemetryPing.manifest
 @BINPATH@/components/messageWakeupService.js
 @BINPATH@/components/messageWakeupService.manifest
 @BINPATH@/components/SettingsManager.js
 @BINPATH@/components/SettingsManager.manifest
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -971,16 +971,17 @@ xpicleanup@BIN_SUFFIX@
   components/Webapps.manifest
   components/WebContentConverter.js
   defaults/autoconfig/platform.js
   defaults/autoconfig/prefcalls.js
   defaults/pref/firefox-branding.js
   defaults/pref/firefox.js
   defaults/pref/firefox-l10n.js
   defaults/pref/services-sync.js
+  defaults/pref/services-captivedetect.js
   defaults/profile/bookmarks.html
   defaults/profile/chrome/userChrome-example.css
   defaults/profile/chrome/userContent-example.css
   defaults/profile/localstore.rdf
   defaults/profile/mimeTypes.rdf
   defaults/profile/prefs.js
   greprefs.js
   hyphenation/
--- a/configure.in
+++ b/configure.in
@@ -8369,16 +8369,22 @@ if test -n "$MOZ_SERVICES_NOTIFICATIONS"
 fi
 
 dnl Build Sync Services if required
 AC_SUBST(MOZ_SERVICES_SYNC)
 if test -n "$MOZ_SERVICES_SYNC"; then
   AC_DEFINE(MOZ_SERVICES_SYNC)
 fi
 
+dnl Build Captive Portal Detector if required
+AC_SUBST(MOZ_SERVICES_CAPTIVEDETECT)
+if test -n "$MOZ_SERVICES_CAPTIVEDETECT"; then
+  AC_DEFINE(MOZ_SERVICES_CAPTIVEDETECT)
+fi
+
 dnl ========================================================
 if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then
     MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS=
 fi
 
 if test "$MOZ_APP_COMPONENT_INCLUDE"; then
   AC_DEFINE_UNQUOTED(MOZ_APP_COMPONENT_INCLUDE, "$MOZ_APP_COMPONENT_INCLUDE")
 fi
--- a/content/base/crashtests/205225-1.html
+++ b/content/base/crashtests/205225-1.html
@@ -1,9 +1,9 @@
 <html>
 <head>
 <script type="text/javascript">
-document.createTreeWalker(null, NodeFilter.SHOW_ALL, null, false);
+document.createTreeWalker(null, NodeFilter.SHOW_ALL, null);
 </script>
 </head>
 <body>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/836890.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+
+function boom()
+{
+  var outer = document.createElement("span");
+  var inner = document.createElement("span");
+  outer.dir = "auto";
+  outer.appendChild(inner);
+  inner.appendChild(document.createTextNode("x"));
+  inner.dir = "auto";
+}
+
+</script>
+</head>
+<body onload="boom();"></body>
+</html>
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -123,8 +123,9 @@ load 815477.html
 load 815500.html
 load 816253.html
 load 822691.html
 load 822723.html
 load 824719.html
 load 827190.html
 load 828054.html
 load 829428.html
+load 836890.html
--- a/content/base/src/DirectionalityUtils.cpp
+++ b/content/base/src/DirectionalityUtils.cpp
@@ -704,16 +704,18 @@ void SetAncestorDirectionIfAuto(nsINode*
              "Must be a text node");
 
   Element* parent = aTextNode->GetParentElement();
   while (parent && parent->NodeOrAncestorHasDirAuto()) {
     if (DoesNotParticipateInAutoDirection(parent) || parent->HasFixedDir()) {
       break;
     }
 
+    aTextNode->SetAncestorHasDirAuto();
+
     if (parent->HasDirAuto()) {
       bool resetDirection = false;
 
       if (!parent->HasDirAutoSet()) {
         // Fast path if parent's direction is not yet set by any descendant
         resetDirection = true;
       } else {
         // If parent's direction is already set, we need to know if
--- a/content/base/test/chrome/test_bug635835.xul
+++ b/content/base/test/chrome/test_bug635835.xul
@@ -17,17 +17,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   </body>
 
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 SimpleTest.waitForExplicitFinish();
 const SHOW_ALL = Components.interfaces.nsIDOMNodeFilter.SHOW_ALL;
 
 addLoadEvent(function() {
-  var walker = document.createTreeWalker(document, SHOW_ALL, null, true);
+  var walker = document.createTreeWalker(document, SHOW_ALL, null);
   try {
     walker.currentNode = {};
     walker.nextNode();
   }
   catch (e) {
     // do nothing - this is a crash test
   }
   ok(true, "Crash test passed");
--- a/content/base/test/file_bug416317.xhtml
+++ b/content/base/test/file_bug416317.xhtml
@@ -452,17 +452,17 @@
             var pass = !expect && e.name == "SyntaxError" && e.code == DOMException.SYNTAX_ERR || false;
             assert(pass, type + ".querySelector: " + query);
           }
         }
       }
     }
 
     function check( type, root, expect, fragment ){
-      var walker = document.createTreeWalker( root, NodeFilter.SHOW_ELEMENT, { acceptNode: function(){ return 1; } }, false );
+      var walker = document.createTreeWalker( root, NodeFilter.SHOW_ELEMENT, { acceptNode: function(){ return 1; } } );
 
       while ( walker.nextNode() ) {
         var div = walker.currentNode;
         if ( (div.getAttribute("class") || "").toString().indexOf("unitTest") > -1 &&
             (!fragment || div.getAttribute("id") !== "nofragment") ) {
           // If we're display:none, we need to toggle that when doing computed
           //  style.
           var needToggle =
--- a/content/base/test/test_NodeIterator_basics_filters.xhtml
+++ b/content/base/test/test_NodeIterator_basics_filters.xhtml
@@ -49,17 +49,17 @@
                            3, 1, 4, // script and CDATA block
                            -3, -3, -3); // close close close
                                         // these aren't there
                                         // not sure why
   var found = new Array();
 
   var iterator = document.createNodeIterator(document,
                                              NodeFilter.SHOW_ALL,
-                                             null, false);
+                                             null);
   var node;
 
   // forwards
   while (node = iterator.nextNode())
     found.push(node.nodeType);
   compare_arrays(expected, found, 'basics forward');
 
   // backwards
@@ -91,17 +91,17 @@
                            1, // div#content
                            8, // comment
                            // processing instruction skipped
                            1, // pre#test
                            1, 4); // script and CDATA block
 
   found.length = 0;
   iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL,
-                                         filter, false);
+                                         filter);
 
   // forwards
   while (node = iterator.nextNode())
     found.push(node.nodeType);
   compare_arrays(expect_f, found, 'filtered forward');
 
   // backwards
   found.length = 0;
@@ -111,17 +111,17 @@
 
   function checkBadFilter(method, n) {
     var iterator =
       document.createNodeIterator(document, NodeFilter.SHOW_ALL,
                                   function() {
                                     if (n < 0)
                                       iterator.detach();
                                     return NodeFilter.FILTER_ACCEPT;
-                                  }, false);
+                                  });
     while (--n >= 0)
       iterator.nextNode();
     try {
       iterator[method]();
       ok(false, "Able to call " + method + " on a detached NodeIterator");
     } catch (x) { ok(true, x) }
   }
   checkBadFilter("nextNode", 2);
@@ -136,18 +136,17 @@
           parent = document.createElement("span");
 
       grandparent.appendChild(parent);
       parent.appendChild(document.createElement("img"));
       parent.appendChild(document.createElement("p"));
 
       return document.createNodeIterator(grandparent,
                                          NodeFilter.SHOW_ALL,
-                                         filter,
-                                         false);
+                                         filter);
     })(function filter(n) {
       if (n.nodeName != "img")
         return NodeFilter.FILTER_ACCEPT;
 
       iterator.detach();
 
       n.parentNode.parentNode.removeChild(n.parentNode);
       // Drop any node references passed into this function.
--- a/content/base/test/test_NodeIterator_mutations_1.xhtml
+++ b/content/base/test/test_NodeIterator_mutations_1.xhtml
@@ -54,17 +54,17 @@
     var root = $('root1');
     var A = $('A');
     var B = $('B');
     var C = $('C');
     var D = $('D');
     var E = $('E');
 
     var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
-					       null, false);
+					       null);
     check(iterator.nextNode(), root, '1.0');
 
     // 1. Remove a node unrelated to the reference node
     remove($('X'));
     check(iterator.nextNode(), A, '1.1');
 
     // 2. Remove an ancestor of the root node
     remove($('Y'));
@@ -82,17 +82,17 @@
   /** Removal of the reference node **/
   (function () {
     var root = $('root2');
     var F = $('F');
     var FF = $('FF');
     var G = $('G');
     var H = $('H');
     var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
-					       null, false);
+					       null);
 
     check(iterator.nextNode(), root, '2.0');
     check(iterator.nextNode(), F,    '2.1');
     check(iterator.nextNode(), FF,   '2.2');
     check(iterator.nextNode(), G,    '2.3');
     remove(G);
     check(iterator.previousNode(), FF, '2.4');
     remove(FF);
@@ -104,17 +104,17 @@
     var root = $('root3');
     var I = $('I');
     var II = $('II');
     var J = $('J');
     var K = $('K');
     var KK = $('KK');
 
     var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
-					       null, false);
+					       null);
     check(iterator.nextNode(), root, '3.0');
     check(iterator.nextNode(), I, '3.1');
     check(iterator.nextNode(), II, '3.2');
     check(iterator.nextNode(), J, '3.3');
     remove(J);
     var X = addChildTo(II);
     check(iterator.nextNode(), X, '3.4');
     check(iterator.previousNode(), X, '3.5');
@@ -130,17 +130,17 @@
   (function () {
     var root = $('root4');
     var L = $('L');
     var M = $('M');
     var MM = $('MM');
     var N = $('N');
 
     var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
-					       null, false);
+					       null);
     check(iterator.nextNode(), root, '4.1');
     check(iterator.nextNode(), L, '4.2');
     check(iterator.nextNode(), M, '4.3');
     check(iterator.nextNode(), MM, '4.4');
     remove(M);
     check(iterator.previousNode(), L, '4.5');
   })();
 
@@ -148,17 +148,17 @@
   (function () {
     var root = $('root5');
     var O = $('O');
     var P = $('P');
     var PP = $('PP');
     var Q = $('Q');
 
     var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
-					       null, false);
+					       null);
     check(iterator.nextNode(), root, '5.1');
     check(iterator.nextNode(), O, '5.2');
     check(iterator.nextNode(), P, '5.3');
     check(iterator.nextNode(), PP, '5.4');
     remove(P);
     var X = addChildTo(O);
     check(iterator.nextNode(), X, '5.5');
   })();
@@ -167,17 +167,17 @@
   (function () {
     var root = $('root6');
     var R = $('R');
     var S = $('S');
     var SS = $('SS');
     var T = $('T');
 
     var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
-					       null, false);
+					       null);
     check(iterator.nextNode(), root, '6.1');
     check(iterator.nextNode(), R, '6.2');
     check(iterator.nextNode(), S, '6.3');
     check(iterator.nextNode(), SS, '6.4');
     check(iterator.previousNode(), SS, '6.5');
     remove(S);
     check(iterator.nextNode(), T, '6.6');
   })();
@@ -186,17 +186,17 @@
   (function () {
     var root = $('root7');
     var U = $('U');
     var V = $('V');
     var VV = $('VV');
     var W = $('W');
 
     var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL,
-					       null, false);
+					       null);
     check(iterator.nextNode(), root, '7.1');
     check(iterator.nextNode(), U, '7.2');
     check(iterator.nextNode(), V, '7.3');
     check(iterator.nextNode(), VV, '7.4');
     check(iterator.previousNode(), VV, '7.5');
     remove(V);
     var X = addChildTo(U);
     check(iterator.previousNode(), X, '7.6');
--- a/content/base/test/test_NodeIterator_mutations_2.html
+++ b/content/base/test/test_NodeIterator_mutations_2.html
@@ -34,17 +34,17 @@
   function testNodeFilter(n) {
     if (n.tagName == 'SPAN')
       return NodeFilter.FILTER_ACCEPT;
     return NodeFilter.FILTER_SKIP;
   }
 
   function checkseq(it, root, expect) {
     var checkIt = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
-					      testNodeFilter, false);
+					      testNodeFilter);
     var printedPointer = (it.referenceNode == undefined);
     var string = '';
     var node;
     while ((node = checkIt.nextNode()) != null) {
       if (!printedPointer && it.referenceNode == node) {
         printedPointer = true;
 	var s = '[' + node.id + '] ';
           if (it.pointerBeforeReferenceNode)
@@ -57,32 +57,32 @@
     }
     is(string.slice(0, -1), expect, "sequence check");
   }
 
   // first a basic sanity check [node-iterator-001]
   (function(){
      var root = resetContent();
      var it = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
-					  testNodeFilter, false);
+					  testNodeFilter);
 
      checkseq(it, root, 'A B C D E F G H I');
      it.nextNode();
      checkseq(it, root, '[A] * B C D E F G H I');
      it.previousNode();
      checkseq(it, root, '* [A] B C D E F G H I');
      it.previousNode();
      checkseq(it, root, '* [A] B C D E F G H I');
   })();
 
   // Mutations that should not move the iterator [node-iterator-002]
   (function(){
      var root = resetContent();
      var it = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
-					  testNodeFilter, false);
+					  testNodeFilter);
 
      for (var i = 0; i < 4; i++)
        it.nextNode();
      checkseq(it, root, 'A B C [D] * E F G H I');
 
      root.removeChild($('E'));
      checkseq(it, root, 'A B C [D] * F G H I');
 
@@ -97,16 +97,16 @@
   })();
 
   // 002 complete
 
   /* Template
   (function(){
      var root = resetContent();
      var it = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
-					  testNodeFilter, false);
+					  testNodeFilter);
 
   })();
   */
 </script>
 </pre>
 </body>
 </html>
--- a/content/base/test/test_NodeIterator_mutations_3.html
+++ b/content/base/test/test_NodeIterator_mutations_3.html
@@ -16,17 +16,17 @@
   }
   var initInner = $('content').innerHTML;
   var content = $('content');
   
 
   function resetContent() {
     content.innerHTML = initInner;
     var checkIt = document.createNodeIterator(content, NodeFilter.SHOW_ELEMENT,
-					      testNodeFilter, false);
+					      testNodeFilter);
     var node;
     while ((node = checkIt.nextNode()) != null) {
       if (node.id) {
         window[node.id] = node;
       }
     }
   }
 
@@ -39,17 +39,17 @@
   function testNodeFilter(n) {
     if (n.tagName == 'SPAN')
       return NodeFilter.FILTER_ACCEPT;
     return NodeFilter.FILTER_SKIP;
   }
 
   function checkseq(it, root, expect) {
     var checkIt = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT,
-					      testNodeFilter, false);
+					      testNodeFilter);
     var printedPointer = (it.referenceNode == undefined);
     var string = '';
     var node;
     while ((node = checkIt.nextNode()) != null) {
       if (!printedPointer && it.referenceNode == node) {
         printedPointer = true;
 	var s = '[' + node.id + '] ';
           if (it.pointerBeforeReferenceNode)
@@ -60,17 +60,17 @@
         string += node.id + " ";
       }
     }
     is(string.slice(0, -1), expect, "sequence check");
   }
 
   resetContent();
   var it = document.createNodeIterator(E, NodeFilter.SHOW_ELEMENT,
-                                       testNodeFilter, false);
+                                       testNodeFilter);
   checkseq(it, root, "root B C D * [E] E1 E11");
 
   removeNode(C);
   checkseq(it, root, "root B D * [E] E1 E11");
 
   it.nextNode();
   removeNode(D);
   checkseq(it, root, "root B [E] * E1 E11");
@@ -89,17 +89,17 @@
   it.previousNode();
   it.previousNode();
   it.previousNode();
   it.previousNode();
   checkseq(it, root, "root * [E] E1 E11");
 
   resetContent();
   it = document.createNodeIterator(E, NodeFilter.SHOW_ELEMENT,
-                                   testNodeFilter, false);
+                                   testNodeFilter);
   checkseq(it, root, "root B C D * [E] E1 E11");
 
   it.nextNode();
   it.nextNode();
   checkseq(it, root, "root B C D E [E1] * E11");
 
   it.previousNode();
   it.previousNode();
@@ -114,17 +114,17 @@
   checkseq(it, root, "root C n * [E] E1 E11");
 
   n2 = makeSpan('n2');
   root.insertBefore(n2, C);
   checkseq(it, root, "root n2 C n * [E] E1 E11");
 
   resetContent();
   it = document.createNodeIterator(E, NodeFilter.SHOW_ELEMENT,
-                                   testNodeFilter, false);
+                                   testNodeFilter);
   checkseq(it, root, "root B C D * [E] E1 E11");
 
   removeNode(root);
   checkseq(it, root, "root B C D * [E] E1 E11");
 
   removeNode(B);
   checkseq(it, root, "root C D * [E] E1 E11");
 
--- a/content/base/test/test_bug338541.xhtml
+++ b/content/base/test/test_bug338541.xhtml
@@ -16,17 +16,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 /** Test for Bug 338541 **/
 function getName(aNode, f)
 {
   return (aNode ? aNode.nodeName : "(null)");
 }
 
 function walkDOM()
 {
-  var walker = document.createTreeWalker($('content'), NodeFilter.SHOW_ELEMENT, null, true);
+  var walker = document.createTreeWalker($('content'), NodeFilter.SHOW_ELEMENT, null);
   var output = "";
   while (walker.nextNode())
   {
     output += getName(walker.currentNode) + "\n";
   }
   output += "Final currentNode: " + getName(walker.currentNode);
   is(output, "foo\nbar\nhtml:b\nqux\nbaz\nFinal currentNode: baz","treewalker returns correct nodeName");
   SimpleTest.finish();
--- a/content/base/test/test_bug378969.html
+++ b/content/base/test/test_bug378969.html
@@ -23,17 +23,17 @@ function do_test()
 {
   var XHTMLDocString = '<html xmlns="http://www.w3.org/1999/xhtml">';
   XHTMLDocString += '<body><input/>input</body></html>';
 
   var doc = new DOMParser().parseFromString(XHTMLDocString, "application/xml");
 
   var body = doc.getElementsByTagName("body")[0];
   var filter = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT;
-  var walker = doc.createTreeWalker(body, filter, null, false);
+  var walker = doc.createTreeWalker(body, filter, null);
   walker.currentNode = body.firstChild;
   walker.nextNode();
 
   ok("A" == "A", "A is A");
 
   SimpleTest.finish();
 }
 
--- a/content/base/test/test_bug559526.html
+++ b/content/base/test/test_bug559526.html
@@ -50,45 +50,41 @@ function filter(node) {
   return NodeFilter.FILTER_ACCEPT;
 }
 
 (function testNodeIterator() {
 
   it = document.createNodeIterator(
     document.getElementById("nodes"),
     NodeFilter.SHOW_ELEMENT,
-    filter,
-    false
+    filter
   );
   while (it.nextNode());
 })();
 
 (function testTreeWalker() {
   it = document.createTreeWalker(
     document.getElementById("nodes"),
     NodeFilter.SHOW_ELEMENT,
-    filter,
-    false
+    filter
   );
   while(it.nextNode());
 
   it = document.createTreeWalker(
     document.getElementById("nodes"),
     NodeFilter.SHOW_ELEMENT,
-    filter,
-    false
+    filter
   );
   it.firstChild();
   while(it.nextSibling());
 
   it = document.createTreeWalker(
     document.getElementById("nodes"),
     NodeFilter.SHOW_ELEMENT,
-    filter,
-    false
+    filter
   );
   it.lastChild();
   while(it.previousSibling());
 })();
 
 is(testCount, 4, "Should have tests 3 filter calls!");
 
 </script>
--- a/content/base/test/test_bug625722.html
+++ b/content/base/test/test_bug625722.html
@@ -22,17 +22,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 function testNodeFilter(n) {
   if (n.id == 'A' || n.id == 'A1')
     return NodeFilter.FILTER_SKIP;
   return NodeFilter.FILTER_ACCEPT;
 }
 
 tw = document.createTreeWalker(document.getElementById("root"),
                                NodeFilter.SHOW_ELEMENT,
-                               testNodeFilter, false);
+                               testNodeFilter);
 
 node = tw.firstChild();
 is(node.id, 'B', "First accepted child of root not B");
 
 
 </script>
 </pre>
 </body>
--- a/content/base/test/test_bug628938.html
+++ b/content/base/test/test_bug628938.html
@@ -82,17 +82,17 @@ function regularWalk()
     [ false, "\n  " ],
     [ true, "SPAN" ],
     [ false, "\n  " ],
     [ true, "DIV" ],
     [ false, "foobar" ],
     [ false, "\n" ],
   ];
   var walker = document.createTreeWalker(document.getElementById('content'),
-                                         NodeFilter.SHOW_ALL, null, true);
+                                         NodeFilter.SHOW_ALL, null);
 
   walkTree(walker);
 
   gIdx = 0;
 }
 
 function noWhiteSpaceWalk()
 {
@@ -120,17 +120,17 @@ function noWhiteSpaceWalk()
                                          NodeFilter.SHOW_ALL,
                                          {
                                            acceptNode : function(node) {
                                              if (node.nodeType == Node.TEXT_NODE &&
                                                  !(/[^\t\n\r ]/.test(node.nodeValue)))
                                                return NodeFilter.FILTER_REJECT;
                                              return NodeFilter.FILTER_ACCEPT;
                                            }
-                                         }, true);
+                                         });
 
   walkTree(walker);
 
   gIdx = 0;
 }
 
 function onlyElementsWalk()
 {
@@ -143,17 +143,17 @@ function onlyElementsWalk()
     [ true, "SPAN" ],
     [ true, "DIV" ],
     [ true, "SPAN" ],
     [ true, "DIV" ],
     [ true, "SPAN" ],
     [ true, "DIV" ],
   ];
   var walker = document.createTreeWalker(document.getElementById('content'),
-                                         NodeFilter.SHOW_ELEMENT, null, true);
+                                         NodeFilter.SHOW_ELEMENT, null);
 
   walkTree(walker);
 
   gIdx = 0;
 }
 
 function onlyDivSubTreeWalk()
 {
@@ -182,17 +182,17 @@ function onlyDivSubTreeWalk()
 
                                              while (node) {
                                                if (node.nodeName == "DIV")
                                                  return NodeFilter.FILTER_ACCEPT;
                                                node = node.parentNode;
                                              }
                                              return NodeFilter.FILTER_SKIP;
                                            }
-                                         }, true);
+                                         });
 
   walkTree(walker);
 
   gIdx = 0;
 }
 
 function onlyDivDataWalk()
 {
@@ -215,17 +215,17 @@ function onlyDivDataWalk()
                                          {
                                            acceptNode : function(node) {
                                              if (node.nodeName == "DIV" ||
                                                  (node.parentNode &&
                                                   node.parentNode.nodeName == "DIV"))
                                                return NodeFilter.FILTER_ACCEPT;
                                              return NodeFilter.FILTER_SKIP;
                                            }
-                                         }, true);
+                                         });
 
   walkTree(walker);
 
   gIdx = 0;
 }
 
 regularWalk();
 noWhiteSpaceWalk();
--- a/content/base/test/test_elementTraversal.html
+++ b/content/base/test/test_elementTraversal.html
@@ -75,17 +75,17 @@ is(cc.length, 4, "wrong number of child 
 is(c.childElementCount, 4, "wrong number of child elements");
 
 contents.splice(2, 1);
 contents.splice(3, 1);
 testContent();
 
 tw = document.createTreeWalker(document.documentElement,
                                NodeFilter.SHOW_ELEMENT,
-                               null, false);
+                               null);
 e = document.documentElement;
 
 elemsTested = 0;
 done = false;
 while(!done) {
   is(tw.currentNode, e, "wrong element:" + tw.currentNode + " != " + e);
   elemsTested++;
   
--- a/content/base/test/test_treewalker_nextsibling.xml
+++ b/content/base/test/test_treewalker_nextsibling.xml
@@ -18,18 +18,17 @@ function setPass(aNode) {
 
 SimpleTest.waitForExplicitFinish();
 
 window.addEventListener("load", function() {
   const nsIDOMNodeFilter = SpecialPowers.Ci.nsIDOMNodeFilter;
   var walker = document.createTreeWalker(
     document,
     nsIDOMNodeFilter.SHOW_TEXT | nsIDOMNodeFilter.SHOW_DOCUMENT,
-    null,
-    true
+    null
   );
   setPass(walker.firstChild());
   while (walker.nextSibling()) {
     setPass(walker.currentNode);
   }
 
 /*
 From http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113/traversal.html#Traversal-TreeWalker
@@ -38,17 +37,17 @@ is substantially different from the same
 document. Nodes that are siblings in the TreeWalker view may be children of
 different, widely separated nodes in the original view. For instance, consider a
 NodeFilter that skips all nodes except for Text nodes and the root node of a
 document. In the logical view that results, all text nodes will be siblings and
 appear as direct children of the root node, no matter how deeply nested the
 structure of the original document.
 */
 
-  walker2 = document.createTreeWalker(document, nsIDOMNodeFilter.SHOW_TEXT, null, true);
+  walker2 = document.createTreeWalker(document, nsIDOMNodeFilter.SHOW_TEXT, null);
   while (walker2.nextNode()) {
     var cNode = walker2.currentNode;
     ok(cNode.getUserData("pass"), "Every text node should appear: " + walker2.currentNode.nodeValue);
     walker.currentNode = cNode;
     var parent = walker.parentNode();
     is(parent, document, "parent of text node should be document");
 
     // Check nextSibling's previousSibling.
--- a/content/events/test/test_bug650493.html
+++ b/content/events/test/test_bug650493.html
@@ -13,17 +13,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 function getNodes() {
-  var walker = document.createTreeWalker($('content'), NodeFilter.SHOW_ALL, null, false);
+  var walker = document.createTreeWalker($('content'), NodeFilter.SHOW_ALL, null);
   var nodes = [];
   do {
     nodes.push(walker.currentNode);
   } while(walker.nextNode());
 
   return nodes;
 }
 
@@ -41,26 +41,26 @@ var mutateCount = 0;
 
 check();
 
 // Set up listeners
 root = $('content');
 root.addEventListener("DOMNodeInserted", function(e) {
   mutateCount++;
   is(e.isTrusted, true, "untrusted mutation event");
-  var w = document.createTreeWalker(e.target, NodeFilter.SHOW_ALL, null, false);
+  var w = document.createTreeWalker(e.target, NodeFilter.SHOW_ALL, null);
   do {
     is(nodes.indexOf(w.currentNode), -1, "already have inserted node (" + w.currentNode + ") when " + testName);
     nodes.push(w.currentNode);
   } while(w.nextNode());
 }, false);
 root.addEventListener("DOMNodeRemoved", function(e) {
   mutateCount++;
   is(e.isTrusted, true, "untrusted mutation event");
-  var w = document.createTreeWalker(e.target, NodeFilter.SHOW_ALL, null, false);
+  var w = document.createTreeWalker(e.target, NodeFilter.SHOW_ALL, null);
   do {
     var index = nodes.indexOf(w.currentNode);
     ok(index != -1, "missing removed node (" + w.currentNode + ") when " + testName);
     nodes.splice(index, 1);
   } while(w.nextNode());
 }, false);
 
 testName = "text-only innerHTML";
--- a/content/html/content/src/UndoManager.cpp
+++ b/content/html/content/src/UndoManager.cpp
@@ -1,30 +1,30 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/UndoManager.h"
+#include "mozilla/dom/DOMTransactionBinding.h"
 
 #include "nsDOMClassInfoID.h"
 #include "nsIClassInfo.h"
 #include "nsIXPCScriptable.h"
 #include "nsIVariant.h"
 #include "nsVariant.h"
 #include "nsINode.h"
 #include "nsIDOMDOMTransactionEvent.h"
 #include "nsEventDispatcher.h"
 #include "nsContentUtils.h"
 #include "jsapi.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/ErrorResult.h"
 
-#include "nsIUndoManagerTransaction.h"
-
 // Includes for mutation observer.
 #include "nsIDOMHTMLElement.h"
 #include "nsStubMutationObserver.h"
 #include "nsAutoPtr.h"
 #include "nsTransactionManager.h"
 
 // Includes for attribute changed transaction.
 #include "nsITransaction.h"
@@ -720,61 +720,72 @@ class FunctionCallTxn : public UndoTxn {
   NS_DECL_CYCLE_COLLECTION_CLASS(FunctionCallTxn)
 
   // Flags
   static const uint32_t CALL_ON_REDO = 1;
   static const uint32_t CALL_ON_UNDO = 2;
 
   NS_IMETHOD RedoTransaction();
   NS_IMETHOD UndoTransaction();
-  FunctionCallTxn(nsIUndoManagerTransaction* aTransaction, uint32_t aFlags);
+  FunctionCallTxn(DOMTransaction* aTransaction, uint32_t aFlags);
 protected:
   /**
    * Call a function member on the transaction object with the
    * specified function name.
    */
-  nsresult CallTransactionMember(const char* aFunctionName);
-  nsCOMPtr<nsIUndoManagerTransaction> mTransaction;
+  nsRefPtr<DOMTransaction> mTransaction;
   uint32_t mFlags;
 };
 
 NS_IMPL_CYCLE_COLLECTION_1(FunctionCallTxn, mTransaction)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FunctionCallTxn)
   NS_INTERFACE_MAP_ENTRY(nsITransaction)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(FunctionCallTxn)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(FunctionCallTxn)
 
-FunctionCallTxn::FunctionCallTxn(nsIUndoManagerTransaction* aTransaction,
+FunctionCallTxn::FunctionCallTxn(DOMTransaction* aTransaction,
                                  uint32_t aFlags)
   : mTransaction(aTransaction), mFlags(aFlags) {}
 
 nsresult
 FunctionCallTxn::RedoTransaction()
 {
   if (!(mFlags & CALL_ON_REDO)) {
     return NS_OK;
   }
 
-  mTransaction->Redo();
+  ErrorResult rv;
+  nsRefPtr<DOMTransactionCallback> redo = mTransaction->GetRedo(rv);
+  if (!rv.Failed() && redo) {
+    redo->Call(mTransaction.get(), rv);
+  }
+  // We ignore rv because we want to avoid the rollback behavior of the
+  // nsITransactionManager.
 
   return NS_OK;
 }
 
 nsresult
 FunctionCallTxn::UndoTransaction()
 {
   if (!(mFlags & CALL_ON_UNDO)) {
     return NS_OK;
   }
 
-  mTransaction->Undo();
+  ErrorResult rv;
+  nsRefPtr<DOMTransactionCallback> undo = mTransaction->GetUndo(rv);
+  if (!rv.Failed() && undo) {
+    undo->Call(mTransaction.get(), rv);
+  }
+  // We ignore rv because we want to avoid the rollback behavior of the
+  // nsITransactionManager.
 
   return NS_OK;
 }
 
 /////////////////////////////////////////////////
 // TxnScopeGuard
 /////////////////////////////////////////////////
 namespace mozilla {
@@ -817,33 +828,36 @@ UndoManager::UndoManager(nsIContent* aNo
 {
   SetIsDOMBinding();
   mTxnManager = new nsTransactionManager();
 }
 
 UndoManager::~UndoManager() {}
 
 void
-UndoManager::Transact(JSContext* aCx, nsIUndoManagerTransaction& aTransaction,
+UndoManager::Transact(JSContext* aCx, DOMTransaction& aTransaction,
                       bool aMerge, ErrorResult& aRv)
 {
   if (mIsDisconnected || mInTransaction) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
 
   TxnScopeGuard guard(this);
 
   // First try executing an automatic transaction.
-  AutomaticTransact(&aTransaction, aRv);
 
-  if (aRv.ErrorCode() == NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED) {
-    // If the automatic transaction didn't work due to the function being
-    // undefined, then try a manual transaction.
-    aRv = NS_OK;
+  nsRefPtr<DOMTransactionCallback> executeAutomatic =
+    aTransaction.GetExecuteAutomatic(aRv);
+  if (aRv.Failed()) {
+    return;
+  }
+  if (executeAutomatic) {
+    AutomaticTransact(&aTransaction, executeAutomatic, aRv);
+  } else {
     ManualTransact(&aTransaction, aRv);
   }
 
   if (aRv.Failed()) {
     return;
   }
 
   if (aMerge) {
@@ -856,19 +870,22 @@ UndoManager::Transact(JSContext* aCx, ns
 
   DispatchTransactionEvent(aCx, NS_LITERAL_STRING("DOMTransaction"), 0, aRv);
   if (aRv.Failed()) {
     return;
   }
 }
 
 void
-UndoManager::AutomaticTransact(nsIUndoManagerTransaction* aTransaction,
+UndoManager::AutomaticTransact(DOMTransaction* aTransaction,
+                               DOMTransactionCallback* aCallback,
                                ErrorResult& aRv)
 {
+  MOZ_ASSERT(aCallback);
+
   nsCOMPtr<nsIMutationObserver> mutationObserver =
     new UndoMutationObserver(mTxnManager);
 
   // Transaction to call the "undo" method after the automatic transaction
   // has been undone.
   nsRefPtr<FunctionCallTxn> undoTxn = new FunctionCallTxn(aTransaction,
       FunctionCallTxn::CALL_ON_UNDO);
 
@@ -876,39 +893,39 @@ UndoManager::AutomaticTransact(nsIUndoMa
   // has been redone.
   nsRefPtr<FunctionCallTxn> redoTxn = new FunctionCallTxn(aTransaction,
       FunctionCallTxn::CALL_ON_REDO);
 
   mTxnManager->BeginBatch(aTransaction);
   mTxnManager->DoTransaction(undoTxn);
   mHostNode->AddMutationObserver(mutationObserver);
 
-  nsresult rv = aTransaction->ExecuteAutomatic();
+  aCallback->Call(aTransaction, aRv);
 
   mHostNode->RemoveMutationObserver(mutationObserver);
   mTxnManager->DoTransaction(redoTxn);
   mTxnManager->EndBatch(true);
 
-  if (NS_FAILED(rv)) {
+  if (aRv.Failed()) {
     mTxnManager->RemoveTopUndo();
-    aRv.Throw(rv);
-    return;
   }
 }
 
 void
-UndoManager::ManualTransact(nsIUndoManagerTransaction* aTransaction,
+UndoManager::ManualTransact(DOMTransaction* aTransaction,
                             ErrorResult& aRv)
 {
   nsRefPtr<FunctionCallTxn> txn = new FunctionCallTxn(aTransaction,
       FunctionCallTxn::CALL_ON_REDO | FunctionCallTxn::CALL_ON_UNDO);
 
-  nsresult rv = aTransaction->Execute();
-  if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
+  nsRefPtr<DOMTransactionCallback> execute = aTransaction->GetExecute(aRv);
+  if (!aRv.Failed() && execute) {
+    execute->Call(aTransaction, aRv);
+  }
+  if (aRv.Failed()) {
     return;
   }
 
   mTxnManager->BeginBatch(aTransaction);
   mTxnManager->DoTransaction(txn);
   mTxnManager->EndBatch(true);
 }
 
@@ -943,17 +960,17 @@ UndoManager::GetLength(ErrorResult& aRv)
     return 0;
   }
 
   return numRedo + numUndo;
 }
 
 void
 UndoManager::ItemInternal(uint32_t aIndex,
-                          nsTArray<nsIUndoManagerTransaction*>& aItems,
+                          nsTArray<DOMTransaction*>& aItems,
                           ErrorResult& aRv)
 {
   int32_t numRedo;
   nsresult rv = mTxnManager->GetNumberOfRedoItems(&numRedo);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
@@ -979,39 +996,35 @@ UndoManager::ItemInternal(uint32_t aInde
     // Index is a undo.
     mTxnManager->GetUndoList(getter_AddRefs(txnList));
     // We need to adjust the index because the undo list indices will
     // be in the reverse order.
     listIndex = numRedo + numUndo - aIndex - 1;
   }
 
   // Obtain data from transaction list and convert to list of
-  // nsIUndoManagerTransaction.
+  // DOMTransaction*.
   nsISupports** listData;
   uint32_t listDataLength;
   rv = txnList->GetData(listIndex, &listDataLength, &listData);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
   for (uint32_t i = 0; i < listDataLength; i++) {
-    nsCOMPtr<nsIUndoManagerTransaction> transaction =
-        do_QueryInterface(listData[i]);
-    MOZ_ASSERT(transaction,
-               "Only nsIUndoManagerTransaction should be stored as data.");
-    aItems.AppendElement(transaction);
+    aItems.AppendElement(static_cast<DOMTransaction*>(listData[i]));
     NS_RELEASE(listData[i]);
   }
   NS_Free(listData);
 }
 
 void
 UndoManager::Item(uint32_t aIndex,
-                  Nullable<nsTArray<nsRefPtr<nsIUndoManagerTransaction> > >& aItems,
+                  Nullable<nsTArray<nsRefPtr<DOMTransaction> > >& aItems,
                   ErrorResult& aRv)
 {
   int32_t numRedo;
   nsresult rv = mTxnManager->GetNumberOfRedoItems(&numRedo);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
@@ -1026,23 +1039,23 @@ UndoManager::Item(uint32_t aIndex,
   MOZ_ASSERT(numUndo >= 0, "Number of undo items should not be negative");
 
   if (aIndex >= (uint32_t) numRedo + numUndo) {
     // If the index is out of bounds, then return null.
     aItems.SetNull();
     return;
   }
 
-  nsTArray<nsIUndoManagerTransaction*> transactions;
+  nsTArray<DOMTransaction*> transactions;
   ItemInternal(aIndex, transactions, aRv);
   if (aRv.Failed()) {
     return;
   }
 
-  nsTArray<nsRefPtr<nsIUndoManagerTransaction> >& items = aItems.SetValue();
+  nsTArray<nsRefPtr<DOMTransaction> >& items = aItems.SetValue();
   for (uint32_t i = 0; i < transactions.Length(); i++) {
     items.AppendElement(transactions[i]);
   }
 }
 
 void
 UndoManager::Undo(JSContext* aCx, ErrorResult& aRv)
 {
@@ -1112,17 +1125,17 @@ UndoManager::Redo(JSContext* aCx, ErrorR
   }
 }
 
 void
 UndoManager::DispatchTransactionEvent(JSContext* aCx, const nsAString& aType,
                                       uint32_t aPreviousPosition,
                                       ErrorResult& aRv)
 {
-  nsTArray<nsIUndoManagerTransaction*> items;
+  nsTArray<DOMTransaction*> items;
   ItemInternal(aPreviousPosition, items, aRv);
   if (aRv.Failed()) {
     return;
   }
 
   nsIDocument* ownerDoc = mHostNode->OwnerDoc();
   if (!ownerDoc) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
@@ -1140,26 +1153,22 @@ UndoManager::DispatchTransactionEvent(JS
                                     getter_AddRefs(event));
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
   nsCOMPtr<nsIWritableVariant> transactions = new nsVariant();
 
-  // Unwrap the nsIUndoManagerTransactions into jsvals, then convert
+  // Unwrap the DOMTransactions into jsvals, then convert
   // to nsIVariant then put into a nsIVariant array. Arrays in XPIDL suck.
-  JSObject* obj;
   nsCOMArray<nsIVariant> keepAlive;
   nsTArray<nsIVariant*> transactionItems;
   for (uint32_t i = 0; i < items.Length(); i++) {
-    nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(items[i]);
-    MOZ_ASSERT(wrappedJS, "All transactions should be WrappedJS.");
-    wrappedJS->GetJSObject(&obj);
-    jsval txVal = JS::ObjectValue(*obj);
+    JS::Value txVal = JS::ObjectValue(*items[i]->Callback());
     if (!JS_WrapValue(aCx, &txVal)) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
     nsCOMPtr<nsIVariant> txVariant;
     rv = nsContentUtils::XPConnect()->JSToVariant(aCx, txVal,
                                                   getter_AddRefs(txVariant));
     if (NS_SUCCEEDED(rv)) {
--- a/content/html/content/src/UndoManager.h
+++ b/content/html/content/src/UndoManager.h
@@ -10,40 +10,42 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 #include "mozilla/dom/Nullable.h"
 #include "nsIContent.h"
 
-class nsIUndoManagerTransaction;
 class nsITransactionManager;
 class nsIMutationObserver;
 
 namespace mozilla {
 class ErrorResult;
 namespace dom {
 
+class DOMTransaction;
+class DOMTransactionCallback;
+
 class UndoManager : public nsISupports,
                     public nsWrapperCache
 {
   friend class TxnScopeGuard;
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(UndoManager)
 
   explicit UndoManager(nsIContent* aNode);
 
-  void Transact(JSContext* aCx, nsIUndoManagerTransaction& aTransaction,
+  void Transact(JSContext* aCx, DOMTransaction& aTransaction,
                 bool aMerge, ErrorResult& aRv);
   void Undo(JSContext* aCx, ErrorResult& aRv);
   void Redo(JSContext* acx, ErrorResult& aRv);
   void Item(uint32_t aIndex,
-            Nullable<nsTArray<nsRefPtr<nsIUndoManagerTransaction> > >& aItems,
+            Nullable<nsTArray<nsRefPtr<DOMTransaction> > >& aItems,
             ErrorResult& aRv);
   uint32_t GetLength(ErrorResult& aRv);
   uint32_t GetPosition(ErrorResult& aRv);
   void ClearUndo(ErrorResult& aRv);
   void ClearRedo(ErrorResult& aRv);
   static bool PrefEnabled();
   void Disconnect();
 
@@ -64,31 +66,33 @@ public:
 protected:
   virtual ~UndoManager();
   nsCOMPtr<nsITransactionManager> mTxnManager;
   nsCOMPtr<nsIContent> mHostNode;
 
   /**
    * Executes |aTransaction| as a manual transaction.
    */
-  void ManualTransact(nsIUndoManagerTransaction* aTransaction,
+  void ManualTransact(DOMTransaction* aTransaction,
                       ErrorResult& aRv);
 
   /**
-   * Executes |aTransaction| as an automatic transaction.
+   * Executes |aTransaction| as an automatic transaction, calling
+   * aCallback to do the work.
    */
-  void AutomaticTransact(nsIUndoManagerTransaction* aTransaction,
+  void AutomaticTransact(DOMTransaction* aTransaction,
+                         DOMTransactionCallback* aCallback,
                          ErrorResult& aRv);
 
   /**
    * Appends the transactions in the undo transaction history at |aIndex|
    * to the array |aItems|.
    */
   void ItemInternal(uint32_t aIndex,
-                    nsTArray<nsIUndoManagerTransaction*>& aItems,
+                    nsTArray<DOMTransaction*>& aItems,
                     ErrorResult& aRv);
 
   /**
    * Dispatches an event to the undo scope host.
    * @param aPreviousPosition The index of the transaction that
    *                          triggered the event.
    */
   void DispatchTransactionEvent(JSContext* aCx, const nsAString& aType,
--- a/content/mathml/content/src/nsMathMLElement.cpp
+++ b/content/mathml/content/src/nsMathMLElement.cpp
@@ -16,16 +16,18 @@
 #include "nsIDocument.h"
 #include "nsEventStates.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "mozAutoDocUpdate.h"
 #include "nsIScriptError.h"
 #include "nsContentUtils.h"
 
+#include "mozilla/dom/ElementBinding.h"
+
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 // nsISupports methods:
 
 DOMCI_NODE_DATA(MathMLElement, nsMathMLElement)
 
@@ -936,8 +938,14 @@ nsMathMLElement::UnsetAttr(int32_t aName
        aNameSpaceID == kNameSpaceID_XLink)) {
     // Note: just because we removed a single href attr doesn't mean there's no href,
     // since there are 2 possible namespaces.
     Link::ResetLinkState(!!aNotify, Link::ElementHasHref());
   }
 
   return rv;
 }
+
+JSObject*
+nsMathMLElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
+{
+  return ElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
--- a/content/mathml/content/src/nsMathMLElement.h
+++ b/content/mathml/content/src/nsMathMLElement.h
@@ -22,17 +22,19 @@ class nsMathMLElement : public nsMathMLE
                         public nsIDOMElement,
                         public nsILink,
                         public mozilla::dom::Link
 {
 public:
   nsMathMLElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsMathMLElementBase(aNodeInfo), Link(this),
       mIncrementScriptLevel(false)
-  {}
+  {
+    SetIsDOMBinding();
+  }
 
   // Implementation of nsISupports is inherited from nsMathMLElementBase
   NS_DECL_ISUPPORTS_INHERITED
 
   // Forward implementations of parent interfaces of nsMathMLElement to 
   // our base class
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
@@ -99,13 +101,18 @@ public:
                            nsIAtom* aPrefix, const nsAString& aValue,
                            bool aNotify);
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify);
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+protected:
+  virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope,
+                             bool *aTriedToWrap) MOZ_OVERRIDE;
+
 private:
   bool mIncrementScriptLevel;
 };
 
 #endif // nsMathMLElement_h
--- a/content/media/wmf/WMFByteStream.cpp
+++ b/content/media/wmf/WMFByteStream.cpp
@@ -11,16 +11,17 @@
 
 #include "WMFByteStream.h"
 #include "WMFUtils.h"
 #include "MediaResource.h"
 #include "nsISeekableStream.h"
 #include "mozilla/RefPtr.h"
 #include "nsIThreadPool.h"
 #include "nsXPCOMCIDInternal.h"
+#include <algorithm>
 
 namespace mozilla {
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* gWMFByteStreamLog = nullptr;
 #define LOG(...) PR_LOG(gWMFByteStreamLog, PR_LOG_DEBUG, (__VA_ARGS__))
 #else
 #define LOG(...)
--- a/content/test/unit/test_isequalnode.js
+++ b/content/test/unit/test_isequalnode.js
@@ -369,20 +369,20 @@ function test_isEqualNode_null()
 }
 
 function test_isEqualNode_wholeDoc()
 {
   doc = ParseFile("isequalnode_data.xml");
   var doc2 = ParseFile("isequalnode_data.xml");
   var tw1 =
     doc.createTreeWalker(doc, Components.interfaces.nsIDOMNodeFilter.SHOW_ALL,
-                         null, false);
+                         null);
   var tw2 =
     doc2.createTreeWalker(doc2, Components.interfaces.nsIDOMNodeFilter.SHOW_ALL,
-                          null, false);
+                          null);
   do {
     check_eq_nodes(tw1.currentNode, tw2.currentNode);
     tw1.nextNode();
   } while(tw2.nextNode());
 }
 
 // UTILITY FUNCTIONS
 
--- a/content/test/unit/test_range.js
+++ b/content/test/unit/test_range.js
@@ -128,18 +128,17 @@ function evalXPathInDocumentFragment(aCo
       return C_i.nsIDOMNodeFilter.FILTER_ACCEPT;
     }
   };
 
   // Look for the node matching the step from the document fragment.
   var walker = aContextNode.ownerDocument.createTreeWalker(
                  aContextNode,
                  targetType,
-                 filter,
-                 true);
+                 filter);
   var targetNode = walker.nextNode();
   do_check_neq(targetNode, null);
 
   // Apply our remaining xpath to the found node.
   var expr = aContextNode.ownerDocument.createExpression(realPath, null);
   var result = expr.evaluate(targetNode, UNORDERED_TYPE, null);
   do_check_true(result instanceof C_i.nsIDOMXPathResult);
   return result.singleNodeValue;
@@ -182,18 +181,17 @@ function getParsedDocument(aPath) {
   do_check_true(doc.documentElement.localName != "parsererror");
   do_check_true(doc instanceof C_i.nsIDOMXPathEvaluator);
   do_check_true(doc instanceof C_i.nsIDOMDocument);
 
   // Clean out whitespace.
   var walker = doc.createTreeWalker(doc,
                                     C_i.nsIDOMNodeFilter.SHOW_TEXT |
                                     C_i.nsIDOMNodeFilter.SHOW_CDATA_SECTION,
-                                    isWhitespace,
-                                    false);
+                                    isWhitespace);
   while (walker.nextNode()) {
     var parent = walker.currentNode.parentNode;
     parent.removeChild(walker.currentNode);
     walker.currentNode = parent;
   }
 
   // Clean out mandatory splits between nodes.
   var splits = doc.getElementsByTagName("split");
@@ -274,18 +272,17 @@ function run_extract_test() {
     } else {
       do_check_eq(extractFrag.firstChild, null);
     }
     do_check_true(baseFrag.isEqualNode(resultFrag));
 
     dump("Ensure the original nodes weren't extracted - test " + i + "\n\n");
     var walker = doc.createTreeWalker(baseFrag,
 				      C_i.nsIDOMNodeFilter.SHOW_ALL,
-				      null,
-				      false);
+				      null);
     var foundStart = false;
     var foundEnd = false;
     do {
       if (walker.currentNode == startContainer) {
         foundStart = true;
       }
 
       if (walker.currentNode == endContainer) {
@@ -308,18 +305,17 @@ function run_extract_test() {
     var startContainer = baseRange.startContainer;
     var endContainer = baseRange.endContainer;
     baseRange.deleteContents();
     do_check_true(baseFrag.isEqualNode(resultFrag));
 
     dump("Ensure the original nodes weren't deleted - test " + i + "\n\n");
     walker = doc.createTreeWalker(baseFrag,
                                   C_i.nsIDOMNodeFilter.SHOW_ALL,
-                                  null,
-                                  false);
+                                  null);
     foundStart = false;
     foundEnd = false;
     do {
       if (walker.currentNode == startContainer) {
         foundStart = true;
       }
 
       if (walker.currentNode == endContainer) {
--- a/content/test/unit/test_treewalker.js
+++ b/content/test/unit/test_treewalker.js
@@ -14,13 +14,13 @@ function test_treeWalker_currentNode()
 {
   var XHTMLDocString = '<html xmlns="http://www.w3.org/1999/xhtml">';
   XHTMLDocString += '<body><input/>input</body></html>';
 
   var doc = ParseXML(XHTMLDocString);
 
   var body = doc.getElementsByTagName("body")[0];
   var filter = I.nsIDOMNodeFilter.SHOW_ELEMENT | I.nsIDOMNodeFilter.SHOW_TEXT;
-  var walker = doc.createTreeWalker(body, filter, null, false);
+  var walker = doc.createTreeWalker(body, filter, null);
   walker.currentNode = body.firstChild;
   walker.nextNode();
 }
 
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -14,16 +14,17 @@
 #define mozilla_dom_BindingDeclarations_h__
 
 #include "nsStringGlue.h"
 #include "jsapi.h"
 #include "mozilla/Util.h"
 #include "nsCOMPtr.h"
 #include "nsDOMString.h"
 #include "nsStringBuffer.h"
+#include "nsTArray.h"
 
 namespace mozilla {
 namespace dom {
 
 struct MainThreadDictionaryBase
 {
 protected:
   JSContext* ParseJSON(const nsAString& aJSON,
@@ -207,12 +208,178 @@ private:
 
   // For callees that know we exist, we can be a stringbuffer/length/null-flag
   // triple.
   nsStringBuffer* mStringBuffer;
   uint32_t mLength;
   bool mIsNull;
 };
 
+// Class for representing optional arguments.
+template<typename T>
+class Optional
+{
+public:
+  Optional()
+  {}
+
+  bool WasPassed() const
+  {
+    return !mImpl.empty();
+  }
+
+  void Construct()
+  {
+    mImpl.construct();
+  }
+
+  template <class T1>
+  void Construct(const T1 &t1)
+  {
+    mImpl.construct(t1);
+  }
+
+  template <class T1, class T2>
+  void Construct(const T1 &t1, const T2 &t2)
+  {
+    mImpl.construct(t1, t2);
+  }
+
+  const T& Value() const
+  {
+    return mImpl.ref();
+  }
+
+  T& Value()
+  {
+    return mImpl.ref();
+  }
+
+  // If we ever decide to add conversion operators for optional arrays
+  // like the ones Nullable has, we'll need to ensure that Maybe<> has
+  // the boolean before the actual data.
+
+private:
+  // Forbid copy-construction and assignment
+  Optional(const Optional& other) MOZ_DELETE;
+  const Optional &operator=(const Optional &other) MOZ_DELETE;
+
+  Maybe<T> mImpl;
+};
+
+// Specialization for strings.
+// XXXbz we can't pull in FakeDependentString here, because it depends on
+// internal strings.  So we just have to forward-declare it and reimplement its
+// ToAStringPtr.
+
+struct FakeDependentString;
+
+template<>
+class Optional<nsAString>
+{
+public:
+  Optional() : mPassed(false) {}
+
+  bool WasPassed() const
+  {
+    return mPassed;
+  }
+
+  void operator=(const nsAString* str)
+  {
+    MOZ_ASSERT(str);
+    mStr = str;
+    mPassed = true;
+  }
+
+  // If this code ever goes away, remove the comment pointing to it in the
+  // FakeDependentString class in BindingUtils.h.
+  void operator=(const FakeDependentString* str)
+  {
+    MOZ_ASSERT(str);
+    mStr = reinterpret_cast<const nsDependentString*>(str);
+    mPassed = true;
+  }
+
+  const nsAString& Value() const
+  {
+    MOZ_ASSERT(WasPassed());
+    return *mStr;
+  }
+
+private:
+  // Forbid copy-construction and assignment
+  Optional(const Optional& other) MOZ_DELETE;
+  const Optional &operator=(const Optional &other) MOZ_DELETE;
+
+  bool mPassed;
+  const nsAString* mStr;
+};
+
+// Class for representing sequences in arguments.  We use an auto array that can
+// hold 16 elements, to avoid having to allocate in common cases.  This needs to
+// be fallible because web content controls the length of the array, and can
+// easily try to create very large lengths.
+template<typename T>
+class Sequence : public AutoFallibleTArray<T, 16>
+{
+public:
+  Sequence() : AutoFallibleTArray<T, 16>()
+  {}
+};
+
+class RootedJSValue
+{
+public:
+  RootedJSValue()
+    : mCx(nullptr)
+  {}
+
+  ~RootedJSValue()
+  {
+    if (mCx) {
+      JS_RemoveValueRoot(mCx, &mValue);
+    }
+  }
+
+  bool SetValue(JSContext* aCx, JS::Value aValue)
+  {
+    // We don't go ahead and root if v is null, because we want to allow
+    // null-initialization even when there is no cx.
+    MOZ_ASSERT_IF(!aValue.isNull(), aCx);
+
+    // Be careful to not clobber mCx if it's already set, just in case we're
+    // being null-initialized (with a null cx for some reason) after we have
+    // already been initialized properly with a non-null value.
+    if (!aValue.isNull() && !mCx) {
+      if (!JS_AddNamedValueRoot(aCx, &mValue, "RootedJSValue::mValue")) {
+        return false;
+      }
+      mCx = aCx;
+    }
+
+    mValue = aValue;
+    return true;
+  }
+
+  operator JS::Value()
+  {
+    return mValue;
+  }
+
+  operator const JS::Value() const
+  {
+    return mValue;
+  }
+
+private:
+  // Don't allow copy-construction of these objects, because it'll do the wrong
+  // thing with our flag mCx.
+  RootedJSValue(const RootedJSValue&) MOZ_DELETE;
+
+  JS::Value mValue;
+  JSContext* mCx;
+};
+
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_BindingDeclarations_h__
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -18,16 +18,17 @@
 
 #include "nsIXPConnect.h"
 #include "qsObjectHelper.h"
 #include "xpcpublic.h"
 #include "nsTraceRefcnt.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/Likely.h"
 #include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/CallbackObject.h"
 
 // nsGlobalWindow implements nsWrapperCache, but doesn't always use it. Don't
 // try to use it without fixing that first.
 class nsGlobalWindow;
 
 namespace mozilla {
 namespace dom {
 
@@ -1115,28 +1116,46 @@ struct GetParentObject<T, false>
 {
   static JSObject* Get(JSContext* cx, JSObject* obj)
   {
     MOZ_CRASH();
     return nullptr;
   }
 };
 
+MOZ_ALWAYS_INLINE
+JSObject* GetJSObjectFromCallback(CallbackObject* callback)
+{
+  return callback->Callback();
+}
+
+MOZ_ALWAYS_INLINE
+JSObject* GetJSObjectFromCallback(void* noncallback)
+{
+  return nullptr;
+}
+
 template<typename T>
 static inline JSObject*
 WrapCallThisObject(JSContext* cx, JSObject* scope, const T& p)
 {
-  // WrapNativeParent is a bit of a Swiss army knife that will
-  // wrap anything for us.
-  JSObject* obj = WrapNativeParent(cx, scope, p);
+  // Callbacks are nsISupports, so WrapNativeParent will just happily wrap them
+  // up as an nsISupports XPCWrappedNative... which is not at all what we want.
+  // So we need to special-case them.
+  JSObject* obj = GetJSObjectFromCallback(p);
   if (!obj) {
-    return nullptr;
+    // WrapNativeParent is a bit of a Swiss army knife that will
+    // wrap anything for us.
+    obj = WrapNativeParent(cx, scope, p);
+    if (!obj) {
+      return nullptr;
+    }
   }
 
-  // But it won't necessarily put things in the compartment of cx.
+  // But all that won't necessarily put things in the compartment of cx.
   if (!JS_WrapObject(cx, &obj)) {
     return nullptr;
   }
 
   return obj;
 }
 
 // Helper for calling WrapNewBindingObject with smart pointers
@@ -1410,16 +1429,18 @@ struct FakeDependentString {
     mLength = 0;
   }
 
   void SetNull() {
     Truncate();
     mFlags |= nsDependentString::F_VOIDED;
   }
 
+  // If this ever changes, change the corresponding code in the
+  // Optional<nsAString> specialization as well.
   const nsAString* ToAStringPtr() const {
     return reinterpret_cast<const nsDependentString*>(this);
   }
 
   nsAString* ToAStringPtr() {
     return reinterpret_cast<nsDependentString*>(this);
   }
 
@@ -1502,107 +1523,16 @@ ConvertJSValueToString(JSContext* cx, co
   if (!chars) {
     return false;
   }
 
   result.SetData(chars, len);
   return true;
 }
 
-// Class for representing optional arguments.
-template<typename T>
-class Optional {
-public:
-  Optional() {}
-
-  bool WasPassed() const {
-    return !mImpl.empty();
-  }
-
-  void Construct() {
-    mImpl.construct();
-  }
-
-  template <class T1>
-  void Construct(const T1 &t1) {
-    mImpl.construct(t1);
-  }
-
-  template <class T1, class T2>
-  void Construct(const T1 &t1, const T2 &t2) {
-    mImpl.construct(t1, t2);
-  }
-
-  const T& Value() const {
-    return mImpl.ref();
-  }
-
-  T& Value() {
-    return mImpl.ref();
-  }
-
-  // If we ever decide to add conversion operators for optional arrays
-  // like the ones Nullable has, we'll need to ensure that Maybe<> has
-  // the boolean before the actual data.
-
-private:
-  // Forbid copy-construction and assignment
-  Optional(const Optional& other) MOZ_DELETE;
-  const Optional &operator=(const Optional &other) MOZ_DELETE;
-  
-  Maybe<T> mImpl;
-};
-
-// Specialization for strings.
-template<>
-class Optional<nsAString> {
-public:
-  Optional() : mPassed(false) {}
-
-  bool WasPassed() const {
-    return mPassed;
-  }
-
-  void operator=(const nsAString* str) {
-    MOZ_ASSERT(str);
-    mStr = str;
-    mPassed = true;
-  }
-
-  void operator=(const FakeDependentString* str) {
-    MOZ_ASSERT(str);
-    mStr = str->ToAStringPtr();
-    mPassed = true;
-  }
-
-  const nsAString& Value() const {
-    MOZ_ASSERT(WasPassed());
-    return *mStr;
-  }
-
-private:
-  // Forbid copy-construction and assignment
-  Optional(const Optional& other) MOZ_DELETE;
-  const Optional &operator=(const Optional &other) MOZ_DELETE;
-  
-  bool mPassed;
-  const nsAString* mStr;
-};
-
-// Class for representing sequences in arguments.  We use an auto array that can
-// hold 16 elements, to avoid having to allocate in common cases.  This needs to
-// be fallible because web content controls the length of the array, and can
-// easily try to create very large lengths.
-template<typename T>
-class Sequence : public AutoFallibleTArray<T, 16>
-{
-public:
-  Sequence() : AutoFallibleTArray<T, 16>() {}
-};
-
 // Class for holding the type of members of a union. The union type has an enum
 // to keep track of which of its UnionMembers has been constructed.
 template<class T>
 class UnionMember {
     AlignedStorage2<T> storage;
 
 public:
     T& SetValue() {
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -317,22 +317,16 @@ DOMInterfaces = {
     'headerFile': 'nsDOMFile.h',
     'resultNotAddRefed': [ 'item' ]
 },
 
 'FileReaderSync': {
     'workers': True,
 },
 
-'DOMTransaction': [
-{
-    'nativeType': 'nsIUndoManagerTransaction',
-    'headerFile': 'nsIUndoManagerTransaction.h',
-}],
-
 'UndoManager': [
 {
     'implicitJSContext' : [ 'undo', 'redo', 'transact' ]
 }],
 
 'FormData': [
 {
     'nativeType': 'nsFormData'
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -2474,18 +2474,17 @@ for (uint32_t i = 0; i < length; ++i) {
     if type.isGeckoInterface():
         assert not isEnforceRange and not isClamp
 
         descriptor = descriptorProvider.getDescriptor(
             type.unroll().inner.identifier.name)
 
         if (descriptor.interface.isCallback() and
             descriptor.interface.identifier.name != "NodeFilter" and
-            descriptor.interface.identifier.name != "EventListener" and
-            descriptor.interface.identifier.name != "DOMTransaction"):
+            descriptor.interface.identifier.name != "EventListener"):
             if descriptor.workers:
                 if type.nullable():
                     declType = CGGeneric("JSObject*")
                 else:
                     declType = CGGeneric("NonNull<JSObject>")
                 conversion = "  ${declName} = &${val}.toObject();\n"
             else:
                 name = descriptor.interface.identifier.name
@@ -2826,23 +2825,31 @@ for (uint32_t i = 0; i < length; ++i) {
                 type,
                 "${declName} = nullptr",
                 failureCode)
         return (template, declType, None, isOptional)
 
     if type.isAny():
         assert not isEnforceRange and not isClamp
 
-        if isMember:
-            raise TypeError("Can't handle member 'any'; need to sort out "
-                            "rooting issues")
-        templateBody = "${declName} = ${val};"
-        templateBody = handleDefaultNull(templateBody,
-                                         "${declName} = JS::NullValue()")
-        return (templateBody, CGGeneric("JS::Value"), None, isOptional)
+        if isMember == "Dictionary":
+            declType = "RootedJSValue"
+            templateBody = ("if (!${declName}.SetValue(cx, ${val})) {\n"
+                            "  return false;\n"
+                            "}")
+            nullHandling = "${declName}.SetValue(nullptr, JS::NullValue())"
+        elif isMember:
+            raise TypeError("Can't handle sequence member 'any'; need to sort "
+                            "out rooting issues")
+        else:
+            declType = "JS::Value"
+            templateBody = "${declName} = ${val};"
+            nullHandling = "${declName} = JS::NullValue()"
+        templateBody = handleDefaultNull(templateBody, nullHandling)
+        return (templateBody, CGGeneric(declType), None, isOptional)
 
     if type.isObject():
         assert not isEnforceRange and not isClamp
 
         if isMember and isMember != "Dictionary":
             raise TypeError("Can't handle member 'object' not in a dictionary;"
                             "need to sort out rooting issues")
 
@@ -3317,18 +3324,17 @@ if (!returnArray) {
 }\n""" % (result, exceptionCodeIndented.define(),
           innerTemplate,
           CGIndenter(exceptionCodeIndented, 4).define())) +
                 setValue("JS::ObjectValue(*returnArray)"), False)
 
     if (type.isGeckoInterface() and
         (not type.isCallbackInterface() or
          type.unroll().inner.identifier.name == "EventListener" or
-         type.unroll().inner.identifier.name == "NodeFilter" or
-         type.unroll().inner.identifier.name == "DOMTransaction")):
+         type.unroll().inner.identifier.name == "NodeFilter")):
         descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
         if type.nullable():
             wrappingCode = ("if (!%s) {\n" % (result) +
                             CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
                             "}\n")
         else:
             wrappingCode = ""
 
@@ -7278,18 +7284,17 @@ class CGNativeMember(ClassMethod):
         if type.isUnion():
             if type.nullable():
                 type = type.inner
             return str(type), True, True
 
         if (type.isGeckoInterface() and
             (not type.isCallbackInterface() or
              type.unroll().inner.identifier.name == "NodeFilter" or
-             type.unroll().inner.identifier.name == "EventListener" or
-             type.unroll().inner.identifier.name == "DOMTransaction")):
+             type.unroll().inner.identifier.name == "EventListener")):
             iface = type.unroll().inner
             argIsPointer = type.nullable() or iface.isExternal()
             forceOwningType = iface.isCallback() or isMember
             if argIsPointer:
                 if (optional or isMember) and forceOwningType:
                     typeDecl = "nsRefPtr<%s>"
                 else:
                     typeDecl = "%s*"
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -528,16 +528,17 @@ dictionary Dict : ParentDict {
   TestEnum otherEnum = "b";
   DOMString otherStr = "def";
   DOMString? yetAnotherStr = null;
   DOMString template;
   object someObj;
   boolean prototype;
   object? anotherObj = null;
   TestCallback? someCallback = null;
+  any someAny;
 };
 
 dictionary ParentDict : GrandparentDict {
   long c = 5;
   TestInterface someInterface;
   TestExternalInterface someExternalInterface;
 };
 
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -221,28 +221,32 @@ BluetoothAdapter::SetPropertyByValue(con
   } else if (name.EqualsLiteral("Class")) {
     mClass = value.get_uint32_t();
   } else if (name.EqualsLiteral("UUIDs")) {
     mUuids = value.get_ArrayOfnsString();
     nsresult rv;
     nsIScriptContext* sc = GetContextForEventHandlers(&rv);
     NS_ENSURE_SUCCESS_VOID(rv);
 
-    if (!SetJsObject(sc->GetNativeContext(), value, mJsUuids)) {
+    if (NS_FAILED(nsTArrayToJSArray(sc->GetNativeContext(),
+                                    mUuids,
+                                    &mJsUuids))) {
       NS_WARNING("Cannot set JS UUIDs object!");
       return;
     }
     Root();
   } else if (name.EqualsLiteral("Devices")) {
     mDeviceAddresses = value.get_ArrayOfnsString();
     nsresult rv;
     nsIScriptContext* sc = GetContextForEventHandlers(&rv);
     NS_ENSURE_SUCCESS_VOID(rv);
 
-    if (!SetJsObject(sc->GetNativeContext(), value, mJsDeviceAddresses)) {
+    if (NS_FAILED(nsTArrayToJSArray(sc->GetNativeContext(),
+                                    mDeviceAddresses,
+                                    &mJsDeviceAddresses))) {
       NS_WARNING("Cannot set JS Devices object!");
       return;
     }
     Root();
   } else {
 #ifdef DEBUG
     nsCString warningMsg;
     warningMsg.AssignLiteral("Not handling adapter property: ");
@@ -571,17 +575,17 @@ BluetoothAdapter::SetPinCode(const nsASt
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
   if(!bs->SetPinCodeInternal(aDeviceAddress, aPinCode, results)) {
     NS_WARNING("SetPinCode failed!");
     return NS_ERROR_FAILURE;
   }
 
   req.forget(aRequest);
-  return NS_OK;  
+  return NS_OK;
 }
 
 nsresult
 BluetoothAdapter::SetPasskey(const nsAString& aDeviceAddress, uint32_t aPasskey,
                              nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
   nsresult rv;
@@ -594,17 +598,17 @@ BluetoothAdapter::SetPasskey(const nsASt
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
   if(bs->SetPasskeyInternal(aDeviceAddress, aPasskey, results)) {
     NS_WARNING("SetPasskeyInternal failed!");
     return NS_ERROR_FAILURE;
   }
 
   req.forget(aRequest);
-  return NS_OK;  
+  return NS_OK;
 }
 
 nsresult
 BluetoothAdapter::SetPairingConfirmation(const nsAString& aDeviceAddress,
                                          bool aConfirmation,
                                          nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
@@ -620,17 +624,17 @@ BluetoothAdapter::SetPairingConfirmation
   if(!bs->SetPairingConfirmationInternal(aDeviceAddress,
                                          aConfirmation,
                                          results)) {
     NS_WARNING("SetPairingConfirmation failed!");
     return NS_ERROR_FAILURE;
   }
 
   req.forget(aRequest);
-  return NS_OK;  
+  return NS_OK;
 }
 
 nsresult
 BluetoothAdapter::SetAuthorization(const nsAString& aDeviceAddress, bool aAllow,
                                    nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
   nsresult rv;
@@ -643,17 +647,17 @@ BluetoothAdapter::SetAuthorization(const
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
   if(!bs->SetAuthorizationInternal(aDeviceAddress, aAllow, results)) {
     NS_WARNING("SetAuthorization failed!");
     return NS_ERROR_FAILURE;
   }
 
   req.forget(aRequest);
-  return NS_OK;  
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 BluetoothAdapter::Connect(const nsAString& aDeviceAddress,
                           uint16_t aProfileId,
                           nsIDOMDOMRequest** aRequest)
 {
   nsCOMPtr<nsIDOMDOMRequest> req;
--- a/dom/bluetooth/BluetoothDevice.cpp
+++ b/dom/bluetooth/BluetoothDevice.cpp
@@ -7,16 +7,18 @@
 #include "base/basictypes.h"
 #include "BluetoothDevice.h"
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothService.h"
 #include "BluetoothUtils.h"
 
 #include "nsDOMClassInfo.h"
 #include "nsContentUtils.h"
+#include "nsTArrayHelpers.h"
+
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 
 USING_BLUETOOTH_NAMESPACE
 
 DOMCI_DATA(BluetoothDevice, BluetoothDevice)
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothDevice,
                                                nsDOMEventTargetHelper)
@@ -112,29 +114,33 @@ BluetoothDevice::SetPropertyByValue(cons
   } else if (name.EqualsLiteral("Paired")) {
     mPaired = value.get_bool();
   } else if (name.EqualsLiteral("UUIDs")) {
     mUuids = value.get_ArrayOfnsString();
     nsresult rv;
     nsIScriptContext* sc = GetContextForEventHandlers(&rv);
     NS_ENSURE_SUCCESS_VOID(rv);
 
-    if (!SetJsObject(sc->GetNativeContext(), value, mJsUuids)) {
+    if (NS_FAILED(nsTArrayToJSArray(sc->GetNativeContext(),
+                                    mUuids,
+                                    &mJsUuids))) {
       NS_WARNING("Cannot set JS UUIDs object!");
       return;
     }
     Root();
   } else if (name.EqualsLiteral("Services")) {
     mServices = value.get_ArrayOfnsString();
     nsresult rv;
     nsIScriptContext* sc = GetContextForEventHandlers(&rv);
     NS_ENSURE_SUCCESS_VOID(rv);
 
-    if (!SetJsObject(sc->GetNativeContext(), value, mJsServices)) {
-      NS_WARNING("Cannot set JS Devices object!");
+    if (NS_FAILED(nsTArrayToJSArray(sc->GetNativeContext(),
+                                    mServices,
+                                    &mJsServices))) {
+      NS_WARNING("Cannot set JS Services object!");
       return;
     }
     Root();
   } else {
     nsCString warningMsg;
     warningMsg.AssignLiteral("Not handling device property: ");
     warningMsg.Append(NS_ConvertUTF16toUTF8(name));
     NS_WARNING(warningMsg.get());
@@ -164,18 +170,18 @@ void
 BluetoothDevice::Notify(const BluetoothSignal& aData)
 {
   BT_LOG("[D] %s: %s", __FUNCTION__, NS_ConvertUTF16toUTF8(aData.name()).get());
 
   BluetoothValue v = aData.value();
   if (aData.name().EqualsLiteral("PropertyChanged")) {
     NS_ASSERTION(v.type() == BluetoothValue::TArrayOfBluetoothNamedValue,
                  "PropertyChanged: Invalid value type");
-     const InfallibleTArray<BluetoothNamedValue>& arr =
-       v.get_ArrayOfBluetoothNamedValue();
+    const InfallibleTArray<BluetoothNamedValue>& arr =
+      v.get_ArrayOfBluetoothNamedValue();
 
     NS_ASSERTION(arr.Length() == 1,
                  "Got more than one property in a change message!");
     SetPropertyByValue(arr[0]);
   } else {
 #ifdef DEBUG
     nsCString warningMsg;
     warningMsg.AssignLiteral("Not handling device signal: ");
--- a/dom/bluetooth/BluetoothUtils.cpp
+++ b/dom/bluetooth/BluetoothUtils.cpp
@@ -11,72 +11,65 @@
 #include "jsapi.h"
 #include "mozilla/Scoped.h"
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "nsContentUtils.h"
 #include "nsIScriptContext.h"
 #include "nsISystemMessagesInternal.h"
 #include "nsString.h"
 #include "nsTArray.h"
-#include "nsTArrayHelpers.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 bool
 SetJsObject(JSContext* aContext,
             const BluetoothValue& aValue,
             JSObject* aObj)
 {
   MOZ_ASSERT(aContext && aObj);
 
-  if (aValue.type() == BluetoothValue::TArrayOfnsString) {
-    const nsTArray<nsString>& sourceArray = aValue.get_ArrayOfnsString();
-    if (NS_FAILED(nsTArrayToJSArray(aContext, sourceArray, &aObj))) {
-      NS_WARNING("Cannot set JS UUIDs object!");
+  if (aValue.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
+    NS_WARNING("SetJsObject: Invalid parameter type");
+    return false;
+  }
+
+  const nsTArray<BluetoothNamedValue>& arr =
+    aValue.get_ArrayOfBluetoothNamedValue();
+
+  for (uint32_t i = 0; i < arr.Length(); i++) {
+    jsval val;
+    const BluetoothValue& v = arr[i].value();
+    JSString* jsData;
+
+    switch(v.type()) {
+      case BluetoothValue::TnsString:
+        jsData =
+          JS_NewStringCopyN(aContext,
+                            NS_ConvertUTF16toUTF8(v.get_nsString()).get(),
+                            v.get_nsString().Length());
+        NS_ENSURE_TRUE(jsData, false);
+        val = STRING_TO_JSVAL(jsData);
+        break;
+      case BluetoothValue::Tuint32_t:
+        val = INT_TO_JSVAL(v.get_uint32_t());
+        break;
+      case BluetoothValue::Tbool:
+        val = BOOLEAN_TO_JSVAL(v.get_bool());
+        break;
+      default:
+        NS_WARNING("SetJsObject: Parameter is not handled");
+        break;
+    }
+
+    if (!JS_SetProperty(aContext, aObj,
+                        NS_ConvertUTF16toUTF8(arr[i].name()).get(),
+                        &val)) {
+      NS_WARNING("Failed to set property");
       return false;
     }
-  } else if (aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue) {
-    const nsTArray<BluetoothNamedValue>& arr =
-      aValue.get_ArrayOfBluetoothNamedValue();
-
-    for (uint32_t i = 0; i < arr.Length(); i++) {
-      jsval val;
-      const BluetoothValue& v = arr[i].value();
-      JSString* JsData;
-
-      switch(v.type()) {
-        case BluetoothValue::TnsString:
-          JsData =
-            JS_NewStringCopyN(aContext,
-                              NS_ConvertUTF16toUTF8(v.get_nsString()).get(),
-                              v.get_nsString().Length());
-          NS_ENSURE_TRUE(JsData, false);
-          val = STRING_TO_JSVAL(JsData);
-          break;
-        case BluetoothValue::Tuint32_t:
-          val = INT_TO_JSVAL(v.get_uint32_t());
-          break;
-        case BluetoothValue::Tbool:
-          val = BOOLEAN_TO_JSVAL(v.get_bool());
-          break;
-        default:
-          NS_WARNING("SetJsObject: Parameter is not handled");
-          break;
-      }
-
-      if (!JS_SetProperty(aContext, aObj,
-                          NS_ConvertUTF16toUTF8(arr[i].name()).get(),
-                          &val)) {
-        NS_WARNING("Failed to set property");
-        return false;
-      }
-    }
-  } else {
-    NS_WARNING("Not handle the type of BluetoothValue!");
-    return false;
   }
 
   return true;
 }
 
 nsString
 GetObjectPathFromAddress(const nsAString& aAdapterPath,
                          const nsAString& aDeviceAddress)
--- a/dom/contacts/ContactManager.js
+++ b/dom/contacts/ContactManager.js
@@ -380,17 +380,23 @@ ContactManager.prototype = {
           if (DEBUG) debug("no request stored!" + msg.requestID);
         }
         break;
       case "Contacts:GetSimContacts:Return:OK":
         req = this.getRequest(msg.requestID);
         if (req) {
           let result = contacts.map(function(c) {
             let contact = new Contact();
-            contact.init( { name: [c.alphaId], tel: [ { value: c.number } ] } );
+            let prop = {name: [c.alphaId], tel: [ { value: c.number } ]};
+
+            if (c.email) {
+              prop.email = [{value: c.email}];
+            }
+
+            contact.init(prop);
             return contact;
           });
           if (DEBUG) debug("result: " + JSON.stringify(result));
           Services.DOMRequest.fireSuccess(req.request, result);
         } else {
           if (DEBUG) debug("no request stored!" + msg.requestID);
         }
         break;
--- a/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json
+++ b/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json
@@ -134,25 +134,25 @@
   "NodeIterator interface: existence and properties of interface object": true,
   "NodeIterator interface: existence and properties of interface prototype object": true,
   "NodeIterator interface: existence and properties of interface prototype object's \"constructor\" property": true,
   "NodeIterator interface: attribute root": true,
   "NodeIterator interface: attribute referenceNode": true,
   "NodeIterator interface: attribute pointerBeforeReferenceNode": true,
   "NodeIterator interface: attribute whatToShow": true,
   "NodeIterator interface: attribute filter": true,
-  "Stringification of document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false)": "debug",
+  "Stringification of document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null)": "debug",
   "TreeWalker interface: existence and properties of interface object": true,
   "TreeWalker interface: existence and properties of interface prototype object": true,
   "TreeWalker interface: existence and properties of interface prototype object's \"constructor\" property": true,
   "TreeWalker interface: attribute root": true,
   "TreeWalker interface: attribute whatToShow": true,
   "TreeWalker interface: attribute filter": true,
   "TreeWalker interface: attribute currentNode": true,
-  "Stringification of document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false)": "debug",
+  "Stringification of document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null)": "debug",
   "NodeFilter interface: existence and properties of interface object": true,
   "NodeFilter interface: existence and properties of interface prototype object": true,
   "NodeFilter interface: existence and properties of interface prototype object's \"constructor\" property": true,
   "NodeFilter interface: constant FILTER_ACCEPT on interface prototype object": true,
   "NodeFilter interface: constant FILTER_REJECT on interface prototype object": true,
   "NodeFilter interface: constant FILTER_SKIP on interface prototype object": true,
   "NodeFilter interface: constant SHOW_ALL on interface prototype object": true,
   "NodeFilter interface: constant SHOW_ELEMENT on interface prototype object": true,
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_interfaces.html
+++ b/dom/imptests/webapps/DOMCore/tests/approved/test_interfaces.html
@@ -504,16 +504,16 @@ idlArray.add_objects({
 	DocumentFragment: ['document.createDocumentFragment()'],
 	DocumentType: ['document.doctype'],
 	Element: ['element'],
 	Attr: ['document.querySelector("[id]").attributes[0]'],
 	Text: ['document.createTextNode("abc")'],
 	ProcessingInstruction: ['xmlDoc.createProcessingInstruction("abc", "def")'],
 	Comment: ['document.createComment("abc")'],
 	Range: ['document.createRange()', 'detachedRange'],
-	NodeIterator: ['document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false)'],
-	TreeWalker: ['document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false)'],
+	NodeIterator: ['document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null)'],
+	TreeWalker: ['document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null)'],
 	NodeList: ['document.querySelectorAll("script")'],
 	HTMLCollection: ['document.body.children'],
 	DOMTokenList: ['document.body.classList'],
 });
 idlArray.test();
 </script>
--- a/dom/interfaces/html/Makefile.in
+++ b/dom/interfaces/html/Makefile.in
@@ -79,17 +79,16 @@ SDK_XPIDLSRCS =					\
 	nsIDOMMediaError.idl		\
 	nsIDOMTimeRanges.idl		\
 	nsIDOMHTMLByteRanges.idl		\
 	nsIDOMHTMLMediaElement.idl		\
 	nsIDOMHTMLSourceElement.idl		\
 	nsIDOMHTMLVideoElement.idl		\
 	nsIDOMHTMLAudioElement.idl		\
 	nsIDOMValidityState.idl		\
-	nsIUndoManagerTransaction.idl	\
 	nsIDOMMozBrowserFrame.idl		\
 	$(NULL)
 
 XPIDLSRCS = 					\
 	nsIDOMHTMLCanvasElement.idl		\
 	nsIDOMHTMLUnknownElement.idl \
 	nsIMozBrowserFrame.idl \
 	$(NULL)
deleted file mode 100644
--- a/dom/interfaces/html/nsIUndoManagerTransaction.idl
+++ /dev/null
@@ -1,17 +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 "nsISupports.idl"
-
-[scriptable, uuid(3802f155-e0f5-49ba-9972-e1aadcf2fdf0)]
-interface nsIUndoManagerTransaction : nsISupports
-{
-  attribute DOMString label;
-  void executeAutomatic();
-  void execute();
-  void undo();
-  void redo();
-};
-
--- a/dom/media/tests/crashtests/791330.html
+++ b/dom/media/tests/crashtests/791330.html
@@ -11,19 +11,25 @@ https://bugzilla.mozilla.org/show_bug.cg
       document.documentElement.removeAttribute("class");
     }
 
     function runTest() {
       var pc = mozRTCPeerConnection();
       pc.close();
 
       navigator.mozGetUserMedia({audio: true, fake: true}, function (stream) {
-        pc.addStream(stream);
-        pc.createOffer(function (offer) {});
-        finish();
+        try {
+          pc.addStream(stream);
+          pc.createOffer(function (offer) {});
+        }
+        finally {
+          stream.stop();
+
+          finish();
+        }
       }, function () {});
     }
   </script>
 </head>
 
 <body onload="setTimeout(runTest, 100)">
 </body>
 </html>
--- a/dom/media/tests/crashtests/799419.html
+++ b/dom/media/tests/crashtests/799419.html
@@ -13,13 +13,14 @@ https://bugzilla.mozilla.org/show_bug.cg
       var v2 = document.getElementById("pc1video");
       var v3 = document.getElementById("pc2video");
       navigator.mozGetUserMedia({video:true, fake: true},
         function(stream) {}, function() {});
       v0.close();
       v1.close();
     }
   </script>
+</head>
 <body onload="boom()">
 <video id="pc1video" width="100" height="100" controls></video>
 <video id="pc2video" width="100" height="100" controls></video>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/crashtests/837421.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=837421
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Bug 837421</title>
+  <script type="application/javascript">
+    function start() {
+        var o0 = mozRTCPeerConnection();
+        var o1 = new mozRTCIceCandidate({"candidate":"127 15 UDP 1 stun.sipgate.net 134117531 type 2001:db8:85a3:0:0:8a2e:370:3478 rport","sdpMid":"application 3566220586 RTP/AVP 5000","sdpMLineIndex":-32767});
+        o0.connectDataConnection(3478,-1);
+        o0.connectDataConnection(-1,3478,2);
+        var o2 = mozRTCPeerConnection();
+        o2.addIceCandidate(o1);
+        o2.connectDataConnection(-1,3478,0.5);
+        o2.connectDataConnection(3478,-1,0.5);
+        var o3 = new mozRTCIceCandidate({"candidate":"31 2097151 IP 33554431 ::ffff:192.0.2.128 3999799469 type numb.viagenie.ca host","sdpMid":"application 1261077875 RTP/AVP 5000","sdpMLineIndex":16777215});
+        o2.connectDataConnection(1,3478);
+        o2.connectDataConnection(3478,1);
+        try {o2.updateIce()} catch(e) {}
+        o2.addIceCandidate(o3);
+    }
+  </script>
+</head>
+
+<body onload="start();"></body>
+</html>
--- a/dom/media/tests/crashtests/crashtests.list
+++ b/dom/media/tests/crashtests/crashtests.list
@@ -3,10 +3,11 @@ default-preferences pref(media.peerconne
 load 780790.html
 load 791270.html
 load 791278.html
 load 791330.html
 load 799419.html
 load 801227.html
 load 802982.html
 load 812785.html
+load 822197.html
 load 834100.html
-load 822197.html
+load 837421.html
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -215,24 +215,28 @@ NetworkManager.prototype = {
             if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
               this.mRIL.updateRILNetworkInterface();
             }
             // Turn on wifi tethering when the callback is set.
             if (this.waitForConnectionReadyCallback) {
               this.waitForConnectionReadyCallback.call(this);
               this.waitForConnectionReadyCallback = null;
             }
+            // Probing the public network accessibility after routing table is ready
+            CaptivePortalDetectionHelper.notify(CaptivePortalDetectionHelper.EVENT_CONNECT, this.active);
             break;
           case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED:
             // Remove host route for data calls
             if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
                 network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
                 network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
               this.removeHostRoute(network);
             }
+            // Abort ongoing captive portal detection on the wifi interface
+            CaptivePortalDetectionHelper.notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, network);
             this.setAndConfigureActive();
             // Update data connection when Wifi connected/disconnected
             if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
               this.mRIL.updateRILNetworkInterface();
             }
             break;
         }
         break;
@@ -830,16 +834,85 @@ NetworkManager.prototype = {
     // Disable tethering settings when fail to enable it.
     if (isError(code)) {
       this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
       settingsLock.set("tethering.usb.enabled", false, null);
     }
   }
 };
 
+let CaptivePortalDetectionHelper = (function() {
+
+  const EVENT_CONNECT = "Connect";
+  const EVENT_DISCONNECT = "Disconnect";
+  let _ongoingInterface = null;
+  let _available = ("nsICaptivePortalDetector" in Ci);
+  let getService = function () {
+    return Cc['@mozilla.org/services/captive-detector;1'].getService(Ci.nsICaptivePortalDetector);
+  };
+
+  let _performDetection = function (interfaceName, callback) {
+    let capService = getService();
+    let capCallback = {
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalCallback]),
+      prepare: function prepare() {
+        capService.finishPreparation(interfaceName);
+      },
+      complete: function complete(success) {
+        _ongoingInterface = null;
+        callback(success);
+      }
+    };
+
+    // Abort any unfinished captive portal detection.
+    if (_ongoingInterface != null) {
+      capService.abort(_ongoingInterface);
+      _ongoingInterface = null;
+    }
+    capService.checkCaptivePortal(interfaceName, capCallback);
+    _ongoingInterface = interfaceName;
+  };
+
+  let _abort = function (interfaceName) {
+    if (_ongoingInterface !== interfaceName) {
+      return;
+    }
+
+    let capService = getService();
+    capService.abort(_ongoingInterface);
+    _ongoingInterface = null;
+  };
+
+  return {
+    EVENT_CONNECT: EVENT_CONNECT,
+    EVENT_DISCONNECT: EVENT_DISCONNECT,
+    notify: function notify(eventType, network) {
+      switch (eventType) {
+        case EVENT_CONNECT:
+          // perform captive portal detection on wifi interface
+          if (_available && network &&
+              network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
+            _performDetection(network.name, function () {
+              // TODO: bug 837600
+              // We can disconnect wifi in here if user abort the login procedure.
+            });
+          }
+
+          break;
+        case EVENT_DISCONNECT:
+          if (_available &&
+              network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
+            _abort(network.name);
+          }
+          break;
+      }
+    }
+  };
+}());
+
 XPCOMUtils.defineLazyServiceGetter(NetworkManager.prototype, "mRIL",
                                    "@mozilla.org/ril;1",
                                    "nsIRadioInterfaceLayer");
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkManager]);
 
 
 let debug;
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -9145,16 +9145,92 @@ let ICCRecordHelper = {
     }
 
     ICCIOHelper.loadLinearFixedEF({fileId : ICC_EF_PBR,
                                    callback: callback.bind(this),
                                    onerror: onerror});
   },
 
   /**
+   * Read ICC EF_IAP. (Index Administration Phonebook)
+   *
+   * @see TS 131.102, clause 4.4.2.2
+   *
+   * @param fileId       EF id of the IAP.
+   * @param recordNumber The number of the record shall be loaded.
+   * @param onsuccess    Callback to be called when success.
+   * @param onerror      Callback to be called when error.
+   */
+  readIAP: function readIAP(fileId, recordNumber, onsuccess, onerror) {
+    function callback(options) {
+      let strLen = Buf.readUint32();
+      let octetLen = strLen / 2;
+
+      let iap = GsmPDUHelper.readHexOctetArray(octetLen);
+      Buf.readStringDelimiter(strLen);
+
+      if (onsuccess) {
+        onsuccess(iap);
+      }
+    }
+
+    ICCIOHelper.loadLinearFixedEF({fileId: fileId,
+                                   recordNumber: recordNumber,
+                                   callback: callback.bind(this),
+                                   onerror: onerror});
+  },
+
+  /**
+   * Read USIM Phonebook EF_EMAIL.
+   *
+   * @see TS 131.102, clause 4.4.2.13
+   *
+   * @param fileId       EF id of the EMAIL.
+   * @param fileType     The type of the EMAIL, one of the ICC_USIM_TYPE* constants.
+   * @param recordNumber The number of the record shall be loaded.
+   * @param onsuccess    Callback to be called when success.
+   * @param onerror      Callback to be called when error.
+   */
+  readEmail: function readEmail(fileId, fileType, recordNumber, onsuccess, onerror) {
+    function callback(optoins) {
+      let strLen = Buf.readUint32();
+      let octetLen = strLen / 2;
+      let email = null;
+
+      // Read contact's email
+      //
+      // | Byte     | Description                 | Length | M/O
+      // | 1 ~ X    | E-mail Address              |   X    |  M
+      // | X+1      | ADN file SFI                |   1    |  C
+      // | X+2      | ADN file Record Identifier  |   1    |  C
+      // Note: The fields marked as C above are mandatort if the file
+      //       is not type 1 (as specified in EF_PBR)
+      if (fileType == ICC_USIM_TYPE1_TAG) {
+        email = GsmPDUHelper.read8BitUnpackedToString(octetLen);
+      } else {
+        email = GsmPDUHelper.read8BitUnpackedToString(octetLen - 2);
+
+        // Consumes the remaining buffer
+        Buf.seekIncoming(2 * PDU_HEX_OCTET_SIZE); // For ADN SFI and Record Identifier
+      }
+
+      Buf.readStringDelimiter(strLen);
+
+      if (onsuccess) {
+        onsuccess(email);
+      }
+    }
+
+    ICCIOHelper.loadLinearFixedEF({fileId: fileId,
+                                   recordNumber: recordNumber,
+                                   callback: callback.bind(this),
+                                   onerror: onerror});
+  },
+
+  /**
    * Read the PLMNsel (Public Land Mobile Network) from the ICC.
    *
    * See ETSI TS 100.977 section 10.3.4 EF_PLMNsel
    */
   getPLMNSelector: function getPLMNSelector() {
     function callback() {
       if (DEBUG) debug("PLMN Selector: Process PLMN Selector");
 
@@ -9892,28 +9968,100 @@ let ICCContactHelper = {
    * Read contacts from USIM.
    *
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   readUSimContacts: function readUSimContacts(onsuccess, onerror) {
     let gotPbrCb = function gotPbrCb(pbr) {
       if (pbr.adn) {
+        let gotAdnCb = function gotAdnCb(contacts) {
+          // Only try to read contact's email when the email tag is shown in pbr.
+          if (!pbr.email) {
+            if (onsuccess) {
+              onsuccess(contacts)
+            }
+            return;
+          }
+
+          this.readUSimEmails(pbr, contacts, onsuccess, onerror);
+        }.bind(this);
+
         let fileId = pbr.adn.fileId;
-        ICCRecordHelper.readADN(fileId, onsuccess, onerror);
+        ICCRecordHelper.readADN(fileId, gotAdnCb, onerror);
       } else {
         let error = onerror || debug;
         error("Cannot access ADN.");
       }
     }.bind(this);
 
     ICCRecordHelper.readPBR(gotPbrCb, onerror);
   },
 
   /**
+   * Read all contacts' email from USIM.
+   *
+   * @param pbr           The phonebook reference file.
+   * @param contacts      The contacts need to get email.
+   * @param onsuccess     Callback to be called when success.
+   * @param onerror       Callback to be called when error.
+   */
+  readUSimEmails: function readUSimEmails(pbr, contacts, onsuccess, onerror) {
+    (function doReadContactEmail(n) {
+      if (n >= contacts.length) {
+        // All contact's email are readed.
+        if (onsuccess) {
+          onsuccess(contacts);
+        }
+        return;
+      }
+
+      // get n-th contact's email
+      ICCContactHelper.readUSimContactEmail(
+        pbr, contacts[n], doReadContactEmail.bind(this, n + 1), onerror);
+    })(0);
+  },
+
+  /**
+   * Read contact's email from USIM.
+   *
+   * @param pbr           The phonebook reference file.
+   * @param contact       The contact needs to get email.
+   * @param onsuccess     Callback to be called when success.
+   * @param onerror       Callback to be called when error.
+   */
+  readUSimContactEmail: function readUSimContactEmail(pbr, contact, onsuccess, onerror) {
+    let gotRecordIdCb = function gotRecordIdCb(recordId) {
+      if (recordId == 0xff) {
+        // Need not to read EF_EMAIL
+        if (onsuccess) {
+          onsuccess();
+        }
+        return;
+      }
+
+      let fileId = pbr.email.fileId;
+      let fileType = pbr.email.fileType;
+      let gotEmailCb = function gotEmailCb(email) {
+        // Add email into contact if any
+        if (email) {
+          contact.email = email;
+        }
+        if (onsuccess) {
+          onsuccess();
+        }
+      }.bind(this);
+
+      ICCRecordHelper.readEmail(fileId, fileType, recordId, gotEmailCb, onerror);
+    }.bind(this);
+
+    this.getEmailRecordId(pbr, contact, gotRecordIdCb, onerror);
+  },
+
+  /**
    * Read contacts from SIM.
    *
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   readSimContacts: function readSimContacts(onsuccess, onerror) {
     ICCRecordHelper.readADN(ICC_EF_ADN, onsuccess, onerror);
   },
@@ -9944,16 +10092,51 @@ let ICCContactHelper = {
    *
    * @param contact       The contact will be updated.
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   updateSimContact: function updateSimContact(contact, onsuccess, onerror) {
     ICCRecordHelper.updateADN(ICC_EF_ADN, contact, onsuccess, onerror);
   },
+
+  /**
+   * Get the recordId of Email.
+   *
+   * If the fileType of Email is ICC_USIM_TYPE1_TAG, use corresponding ADN recordId.
+   * otherwise get the recordId from IAP.
+   *
+   * @see TS 131.102, clause 4.4.2.2
+   *
+   * @param pbr          The phonebook reference file.
+   * @param contact      The contact will be updated.
+   * @param onsuccess    Callback to be called when success.
+   * @param onerror      Callback to be called when error.
+   */
+  getEmailRecordId: function getEmailRecordId(pbr, contact, onsuccess, onerror) {
+    if (pbr.email.fileType == ICC_USIM_TYPE1_TAG) {
+      // If the file type is ICC_USIM_TYPE1_TAG, use corresponding ADN recordId.
+      if (onsuccess) {
+        onsuccess(contact.recordId);
+      }
+    } else {
+      // If the file type is ICC_USIM_TYPE2_TAG, the recordId shall be got from IAP.
+      let gotIapCb = function gotIapCb(iap) {
+        let indexInIAP = pbr.email.indexInIAP;
+        let recordId = iap[indexInIAP];
+
+        if (onsuccess) {
+          onsuccess(recordId);
+        }
+      }.bind(this);
+
+      let fileId = pbr.iap.fileId;
+      ICCRecordHelper.readIAP(fileId, contact.recordId, gotIapCb, onerror);
+    }
+  },
 };
 
 /**
  * Global stuff.
  */
 
 if (!this.debug) {
   // Debugging stub that goes nowhere.
--- a/dom/system/gonk/tests/test_ril_worker_icc.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc.js
@@ -1614,8 +1614,58 @@ add_test(function test_stk_event_downloa
 
   let event = {
     eventType: STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE
   };
   worker.RIL.sendStkEventDownload({
     event: event
   });
 });
+
+/**
+ * Verify ICCRecordHelper.readEmail
+ */
+add_test(function test_read_email() {
+  let worker = newUint8Worker();
+  let helper = worker.GsmPDUHelper;
+  let record = worker.ICCRecordHelper;
+  let buf    = worker.Buf;
+  let io     = worker.ICCIOHelper;
+
+  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
+    let email_1 = [
+      0x65, 0x6D, 0x61, 0x69, 0x6C,
+      0x00, 0x6D, 0x6F, 0x7A, 0x69,
+      0x6C, 0x6C, 0x61, 0x2E, 0x63,
+      0x6F, 0x6D, 0x02, 0x23];
+
+    // Write data size
+    buf.writeUint32(email_1.length * 2);
+
+    // Write email
+    for (let i = 0; i < email_1.length; i++) {
+      helper.writeHexOctet(email_1[i]);
+    }
+
+    // Write string delimiter
+    buf.writeStringDelimiter(email_1.length * 2);
+
+    if (options.callback) {
+      options.callback(options);
+    }
+  };
+
+  function doTestReadEmail(type, expectedResult) {
+    let fileId = 0x6a75;
+    let recordNumber = 1;
+
+    // fileId and recordNumber are dummy arguments.
+    record.readEmail(fileId, type, recordNumber, function (email) {
+      do_check_eq(email, expectedResult);
+    });
+  };
+
+  doTestReadEmail(ICC_USIM_TYPE1_TAG, "email@mozilla.com$#");
+  doTestReadEmail(ICC_USIM_TYPE2_TAG, "email@mozilla.com");
+
+  run_next_test();
+});
+
--- a/dom/tests/browser/browser_geolocation_privatebrowsing_perwindowpb.js
+++ b/dom/tests/browser/browser_geolocation_privatebrowsing_perwindowpb.js
@@ -5,50 +5,56 @@ function test() {
 
   prefs.setBoolPref("geo.prompt.testing", true);
   prefs.setBoolPref("geo.prompt.testing.allow", true);
 
   const testPageURL = "http://mochi.test:8888/browser/" +
     "dom/tests/browser/browser_geolocation_privatebrowsing_page.html";
   waitForExplicitFinish();
 
+  var windowsToClose = [];
   function testOnWindow(aIsPrivate, aCallback) {
     var win = OpenBrowserWindow({private: aIsPrivate});
-    waitForFocus(aCallback, win);
+    win.addEventListener("load", function onLoad() {
+      win.removeEventListener("load", onLoad, false);
+      windowsToClose.push(win);
+      executeSoon(function() { aCallback(win); });
+    }, false);
   }
 
+  registerCleanupFunction(function () {
+    windowsToClose.forEach(function(win) {
+      win.close();
+    });
+  });
+
   testOnWindow(false, function(aNormalWindow) {
-    aNormalWindow.gBrowser.selectedTab = aNormalWindow.gBrowser.addTab();
     aNormalWindow.gBrowser.selectedBrowser.addEventListener("georesult", function load(ev) {
       aNormalWindow.gBrowser.selectedBrowser.removeEventListener("georesult", load, false);
       is(ev.detail, 200, "unexpected access token");
 
       prefs.setCharPref("geo.wifi.uri", baseProvider + "?desired_access_token=ggg");
-      aNormalWindow.close();
 
       testOnWindow(true, function(aPrivateWindow) {
-        aPrivateWindow.gBrowser.selectedTab = aPrivateWindow.gBrowser.addTab();
         aPrivateWindow.gBrowser.selectedBrowser.addEventListener("georesult", function load2(ev) {
           aPrivateWindow.gBrowser.selectedBrowser.removeEventListener("georesult", load2, false);
           is(ev.detail, 200, "unexpected access token");
 
           prefs.setCharPref("geo.wifi.uri", baseProvider + "?expected_access_token=fff");
-          aPrivateWindow.close();
 
-          testOnWindow(false, function(aNormalWindow) {
-            aNormalWindow.gBrowser.selectedTab = aNormalWindow.gBrowser.addTab();
-            aNormalWindow.gBrowser.selectedBrowser.addEventListener("georesult", function load3(ev) {
-              aNormalWindow.gBrowser.selectedBrowser.removeEventListener("georesult", load3, false);
+          testOnWindow(false, function(aAnotherNormalWindow) {
+            aAnotherNormalWindow.gBrowser.selectedBrowser.addEventListener("georesult", function load3(ev) {
+              aAnotherNormalWindow.gBrowser.selectedBrowser.removeEventListener("georesult", load3, false);
               is(ev.detail, 200, "unexpected access token");
               prefs.setBoolPref("geo.prompt.testing", false);
               prefs.setBoolPref("geo.prompt.testing.allow", false);
-              aNormalWindow.close();
+
               finish();
             }, false, true);
-            aNormalWindow.content.location = testPageURL;
+            aAnotherNormalWindow.content.location = testPageURL;
           });
         }, false, true);
         aPrivateWindow.content.location = testPageURL;
       });
     }, false, true);
     aNormalWindow.content.location = testPageURL;
   });
 }
--- a/dom/tests/mochitest/bugs/test_bug393974.html
+++ b/dom/tests/mochitest/bugs/test_bug393974.html
@@ -27,18 +27,17 @@ function test()
                                      {
                                        // force the closure to contain the
                                        // global object, in case a future
                                        // optimization might minimize the
                                        // function's captured environment
                                        if ("foo" + window == "fooPIRATES!")
                                          return NodeFilter.FILTER_ACCEPT;
                                        return NodeFilter.FILTER_REJECT;
-                                     },
-                                     true);
+                                     });
 
   // That should have been enough to create a leak, but we should do at least
   // a couple tests while we're here so that this document doesn't show up as
   // having no tests pass *or* fail.
 
   ok(tw.firstChild() === null, "shouldn't be a first child");
   ok(tw.currentNode === document, "should be unchanged");
 
--- a/dom/webidl/DOMTransaction.webidl
+++ b/dom/webidl/DOMTransaction.webidl
@@ -5,16 +5,18 @@
  *
  * The origin of this IDL file is
  * http://dvcs.w3.org/hg/undomanager/raw-file/tip/undomanager.html
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
+callback DOMTransactionCallback = void();
+
 callback interface DOMTransaction {
-  attribute DOMString label;
-  void executeAutomatic();
-  void execute();
-  void undo();
-  void redo();
+  readonly attribute DOMString? label;
+  readonly attribute DOMTransactionCallback? executeAutomatic;
+  readonly attribute DOMTransactionCallback? execute;
+  readonly attribute DOMTransactionCallback? undo;
+  readonly attribute DOMTransactionCallback? redo;
 };
 
--- a/dom/webidl/UndoManager.webidl
+++ b/dom/webidl/UndoManager.webidl
@@ -5,18 +5,16 @@
  *
  * The origin of this IDL file is
  * http://dvcs.w3.org/hg/undomanager/raw-file/tip/undomanager.html
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
-interface DOMTransaction;
-
 [PrefControlled]
 interface UndoManager {
   [Throws] void transact(DOMTransaction transaction, boolean merge);
   [Throws] void undo();
   [Throws] void redo();
   [Throws] sequence<DOMTransaction>? item(unsigned long index);
   [Throws] readonly attribute unsigned long length;
   [Throws] readonly attribute unsigned long position;
--- a/dom/workers/URL.cpp
+++ b/dom/workers/URL.cpp
@@ -199,17 +199,19 @@ URL::CreateObjectURL(const WorkerGlobalO
                      nsString& aResult, mozilla::ErrorResult& aRv)
 {
   JSContext* cx = aGlobal.GetContext();
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
 
   nsCOMPtr<nsIDOMBlob> blob = file::GetDOMBlobFromJSObject(aBlob);
   if (!blob) {
     SetDOMStringToNull(aResult);
-    aRv.Throw(NS_ERROR_TYPE_ERR);
+
+    NS_NAMED_LITERAL_STRING(blobStr, "Blob");
+    aRv.ThrowTypeError(MSG_DOES_NOT_IMPLEMENT_INTERFACE, &blobStr);
     return;
   }
 
   nsRefPtr<CreateURLRunnable> runnable =
     new CreateURLRunnable(workerPrivate, blob, aOptions, aResult);
 
   if (!runnable->Dispatch(cx)) {
     JS_ReportPendingException(cx);
--- a/dom/workers/test/url_worker.js
+++ b/dom/workers/test/url_worker.js
@@ -54,10 +54,19 @@ onmessage = function() {
     url = URL.createObjectURL(blob);
     status = true;
   } catch(e) {
   }
 
   postMessage({type: 'status', status: status, msg: 'Blob URL2:' + url});
   postMessage({type: 'url', url: url});
 
+  status = false;
+  try {
+    URL.createObjectURL(new Object());
+  } catch(e) {
+    status = true;
+  }
+
+  postMessage({type: 'status', status: status, msg: 'Exception wanted' });
+
   postMessage({type: 'finish' });
 }
--- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
+++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
@@ -1622,17 +1622,17 @@ nsresult nsWebBrowserPersist::SaveDocume
         mDocList.AppendElement(docData);
 
         // Walk the DOM gathering a list of externally referenced URIs in the uri map
         nsCOMPtr<nsIDOMTreeWalker> walker;
         rv = aDocument->CreateTreeWalker(docAsNode, 
             nsIDOMNodeFilter::SHOW_ELEMENT |
                 nsIDOMNodeFilter::SHOW_DOCUMENT |
                 nsIDOMNodeFilter::SHOW_PROCESSING_INSTRUCTION,
-            nullptr, true, getter_AddRefs(walker));
+            nullptr, 1, getter_AddRefs(walker));
         NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
         nsCOMPtr<nsIDOMNode> currentNode;
         walker->GetCurrentNode(getter_AddRefs(currentNode));
         while (currentNode)
         {
             OnWalkDOMNode(currentNode);
             walker->NextNode(getter_AddRefs(currentNode));
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -6,16 +6,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef LifoAlloc_h__
 #define LifoAlloc_h__
 
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/GuardObjects.h"
+#include "mozilla/ASan.h"
+
+#if defined(MOZ_VALGRIND)
+#include "valgrind/memcheck.h"
+#endif
 
 /*
  * This data structure supports stacky LIFO allocation (mark/release and
  * LifoAllocScope). It does not maintain one contiguous segment; instead, it
  * maintains a bunch of linked memory segments. In order to prevent malloc/free
  * thrashing, unused segments are deallocated when garbage collection occurs.
  */
 
@@ -61,25 +66,40 @@ class BumpChunk
         next_(NULL), bumpSpaceSize(bumpSpaceSize)
     {
         JS_ASSERT(bump == AlignPtr(bump));
     }
 
     void setBump(void *ptr) {
         JS_ASSERT(bumpBase() <= ptr);
         JS_ASSERT(ptr <= limit);
-        mozilla::DebugOnly<char *> prevBump = bump;
+#if defined(DEBUG) || defined(MOZ_ASAN) || defined(MOZ_VALGRIND)
+        char* prevBump = bump;
+#endif
         bump = static_cast<char *>(ptr);
 #ifdef DEBUG
         JS_ASSERT(contains(prevBump));
 
         /* Clobber the now-free space. */
         if (prevBump > bump)
             memset(bump, 0xcd, prevBump - bump);
 #endif
+
+        /* Poison/Unpoison memory that we just free'd/allocated */
+#if defined(MOZ_ASAN)
+        if (prevBump > bump)
+            ASAN_POISON_MEMORY_REGION(bump, prevBump - bump);
+        else if (bump > prevBump)
+            ASAN_UNPOISON_MEMORY_REGION(prevBump, bump - prevBump);
+#elif defined(MOZ_VALGRIND)
+        if (prevBump > bump)
+            VALGRIND_MAKE_MEM_NOACCESS(bump, prevBump - bump);
+        else if (bump > prevBump)
+            VALGRIND_MAKE_MEM_UNDEFINED(prevBump, bump - prevBump);
+#endif
     }
 
   public:
     BumpChunk *next() const { return next_; }
     void setNext(BumpChunk *succ) { next_ = succ; }
 
     size_t used() const { return bump - bumpBase(); }
     size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) {
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug499169.js
@@ -0,0 +1,179 @@
+// Binary: cache/js-dbg-32-30b481fd82f5-linux
+// Flags: -j
+//
+var Native = function(k) {
+    var f = k.initialize;
+    var d = f;
+    var j = function(n, l, o, m) {
+        n.prototype[l] = o;
+    };
+    d.alias = function(n, l, o) {
+        n = this.prototype[n]
+        return j(this, l, n, o);
+    };
+    d.implement = function(m, l, o) {
+        for (var n in m) {
+            j(this, n, m[n], l);
+        }
+    }
+    return d;
+};
+(function() {
+    var a = {
+        Array: Array,
+        Function: Function,
+    };
+    for (var h in a) {
+        new Native({
+            initialize: a[h],
+        });
+    }
+} ());
+Array.alias("forEach", "each");
+function $merge() {
+    var a = Array.slice(arguments);
+    a.unshift({});
+    return $mixin.apply(null, a);
+}
+function $mixin(e) {
+    for (var d = 1, a = arguments.length; d < a; d++) {
+        var b = arguments[d];
+        for (var c in b) {
+            var g = b[c],
+            f = e[c];
+            e[c] = f && $type(g) == "object" && $type(f) == "object" ? $mixin(f, g) : $unlink(g);
+        }
+    }
+}
+function $type(a) {
+    if (a == undefined) {
+        return false;
+    }
+    if (a.$family) {
+    }
+    return typeof a;
+}
+function $unlink(c) {
+    if ($type(c) == "object") {
+        b = {};
+    }
+    return b;
+}
+var Window = new Native({
+    initialize: function(a) {},
+});
+Array.implement({
+    extend: function(c) {
+        return this;
+    }
+});
+Function.implement({
+    extend: function(a) {
+        for (var b in a) {
+            this[b] = a[b];
+        }
+        return this;
+    },
+    run: function(a, b) {
+        return this.apply(b, a);
+    }
+});
+function Class(b) {
+    var a = function() {
+        Object.reset(this);
+        var c = this.initialize ? this.initialize.apply(this, arguments) : this;
+    }.extend(this);
+    a.implement(b);
+    return a;
+}
+Object.reset = function(a, c) {
+    if (c == null) {
+        for (var e in a) {
+            Object.reset(a, e);
+        }
+    }
+    switch ($type(a[c])) {
+    case "object":
+        var d = function() {};
+        d.prototype = a[c];
+        var b = new d;
+        a[c] = Object.reset(b);
+    }
+    return a;
+};
+(new Native({initialize: Class})).extend({});
+    function wrap(a, b, c) {
+        return function() {
+            var d = c.apply(this, arguments);
+        }.extend({});
+    }
+Class.implement({
+    implement: function(a, d) {
+        if ($type(a) == "object") {
+            for (var e in a) {
+                this.implement(e, a[e]);
+            }
+        }
+        var f = Class.Mutators[a];
+        if (f) {
+            d = f.call(this, d);
+        }
+        var c = this.prototype;
+        switch ($type(d)) {
+        case "function":
+            c[a] = wrap(this, a, d);
+            break;
+        case "object":
+            var b = c[a];
+            if ($type(b) == "object") {
+                $mixin(b, d);
+            } else {
+                c[a] = $unlink(d);
+            }
+        }
+    }
+});
+Class.Mutators = {
+    Extends: function(a) {
+        this.prototype = new a;
+    },
+    Implements: function(a) {
+        a.each(function(b) {
+            b = new b;
+            this.implement(b);
+        },
+        this);
+    }
+};
+var Events = new Class({});
+var Options = new Class({
+    setOptions: function() {
+        this.options = $merge.run([this.options].extend(arguments));
+    }
+});
+var Autocompleter = {};
+Autocompleter.Base = new Class({
+    Implements: [Options, Events],
+    options: {},
+});
+Autocompleter.Ajax = {};
+Autocompleter.Ajax.Base = new Class({
+    Extends: Autocompleter.Base,
+    options: {
+        postVar: "value",
+        onRequest: function(){},
+    }
+});
+Autocompleter.Ajax.Json = new Class({
+    Extends: Autocompleter.Ajax.Base,
+});
+Autocompleter.JsonP = new Class({
+    Extends: Autocompleter.Ajax.Json,
+    options: {
+        minLength: 1
+    },
+    initialize: function(el, url, options) {
+        this.setOptions({});
+    }
+});
+new Autocompleter.JsonP();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug505305.js
@@ -0,0 +1,5 @@
+// Binary: cache/js-dbg-32-aa85b2f55960-linux
+// Flags:
+//
+var str = 'afoo$40bar'.substr(1);
+print(str.replace(str, str));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug617485.js
@@ -0,0 +1,6 @@
+// |jit-test| error:SyntaxError
+
+// Binary: cache/js-dbg-64-4c1fbfcf1d0d-linux
+// Flags:
+//
+Iterator(evalcx('#2=*'))
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug677386.js
@@ -0,0 +1,25 @@
+// |jit-test| error:ReferenceError
+
+// Binary: cache/js-dbg-64-82545b1e4129-linux
+// Flags:
+//
+
+var g = newGlobal('new-compartment');
+g.eval("var line0 = Error().lineNumber;\n" +
+       "function f() {\n" +     // line0 + 1
+       "    return 2;\n" +      // line0 + 2
+       "}\n");
+var N = 4;
+for (var i = 0; i < N; i++) {
+    var dbg = Debugger(g);
+    dbg.onDebuggerStatement = function (frame) {
+        var handler = {hit: function () { hits++; }};
+        var s = frame.eval("f").return.script;
+        var offs = s.getLineOffsets(g.line0 + 2);
+        for (var j = 0; j < offs.length; j++)
+            s.setBreakpoint(offs[j], handler);
+    };
+    g.eval('debugger;');
+}
+gc(/c$...$/);
+assertEq(g.f(), 2);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug677587.js
@@ -0,0 +1,11 @@
+// Binary: cache/js-dbg-64-f189dd6316eb-linux
+// Flags:
+//
+
+var g = newGlobal('new-compartment');
+g.eval("var a = {};");
+var dbg = new Debugger;
+var gw = dbg.addDebuggee(g);
+var desc = gw.getOwnPropertyDescriptor("a");
+gw.defineProperty("b", desc);
+Debugger(g.a, g.b);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug677977.js
@@ -0,0 +1,26 @@
+// Binary: cache/js-dbg-64-48e43edc8834-linux
+// Flags:
+//
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+dbg.onDebuggerStatement = function (frame) {
+    var s = frame.eval("f").return.script;
+};
+function test(s) {
+    g.eval("line0 = Error().lineNumber;\n" +
+           "debugger;\n" +          // line0 + 1
+           "function f(i) {\n" +    // line0 + 2
+           "}\n");
+}
+test("i = 128;\n" +  "}\n");
+var hits = 0;
+dbg.onNewScript = function (s) {
+    hits++;
+};
+assertEq(g.eval("eval('2 + 3')"), 5);
+this.gczeal(hits, 2);
+var fn = g.Function("a", "return 5 + a;");
+var g2 = newGlobal('new-compartment');
+dbg.addDebuggee(g2, dbg);
+g2.clone(fn);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug678086.js
@@ -0,0 +1,17 @@
+// |jit-test| error:Error
+
+// Binary: cache/js-dbg-64-48e43edc8834-linux
+// Flags:
+//
+
+function f() {
+    frame = dbg.getNewestFrame();
+}
+var g = newGlobal('new-compartment');
+g.f = function (a, b) { return a + "/" + this . f( ) ; };
+var dbg = Debugger(g);
+dbg.onDebuggerStatement = function (frame) {
+    var f = frame.eval("f").return;
+    assertEq(f.call(null, "a", "b").return, "a/b");
+};
+g.eval("debugger;");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug678529.js
@@ -0,0 +1,11 @@
+// |jit-test| error:Error
+
+// Binary: cache/js-dbg-32-48e43edc8834-linux
+// Flags: -j -m -a
+//
+
+var g = newGlobal('new-compartment');
+var dbg = Debugger(g);
+dbg.onDebuggerStatement = function (stack) { return {return: 1234}; };
+g.eval("function f() { debugger; return 'bad'; }");
+assertEq(new g.f(), 1234);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug690933.js
@@ -0,0 +1,14 @@
+// |jit-test| slow;
+
+// Binary: cache/js-dbg-32-1463dc6308a8-linux
+// Flags:
+//
+
+var fe="vv";
+for (i=0; i<24; i++)
+  fe += fe;
+var fu=new Function(
+  fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe,
+  fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe,
+  "done"
+);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug691593.js
@@ -0,0 +1,18 @@
+// Binary: cache/js-dbg-64-acf3c1fb7c94-linux
+// Flags:
+//
+
+genexp = "x * x for (x in [])";
+genexpParened = "(" + genexp + ")";
+needParens(2, "if (1, xx) { }");
+function needParens(section, pat, exp) {
+  ft = pat.replace(/xx/, genexpParened);
+  try {
+    f = new Function(ft);
+  } catch(e) {  }
+  overParenTest(section, f, exp);
+}
+function overParenTest(section, f, exp) {
+  var uf = "" + f;
+  if (uf.indexOf(genexpParened) != -1) {  }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug691595.js
@@ -0,0 +1,20 @@
+// |jit-test| error:ReferenceError
+
+// Binary: cache/js-dbg-64-acf3c1fb7c94-linux
+// Flags: --ion-eager
+//
+
+function k(f_arg) {
+  for (var i = 0; i < 10; ++i) {
+    f_arg(  ) ;
+  }
+}
+function t() {
+  k(function (i) { actual ^ this | this; });
+}
+var ans = 0;
+for (var j = 0; j < 10; ++j) {
+  for (var i = 0; i < 10; ++i) {
+    ans += t();
+  }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug698148.js
@@ -0,0 +1,16 @@
+// Binary: cache/js-dbg-64-b01eb1ba58ce-linux
+// Flags:
+//
+
+expect = 'Test skipped.';
+function addPointImagedata(pointArray, n, col, row) {
+    pointArray[expect + 2] = 2;
+}
+function createMandelSet() {
+    points = new Array;
+    for (var idx = 0; idx < 1440000 ; ++idx) {
+    	points[idx] = 0
+    }
+    addPointImagedata(points, ({}, {}), 0,0)
+}
+createMandelSet();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug698150.js
@@ -0,0 +1,12 @@
+// Binary: cache/js-dbg-64-b01eb1ba58ce-linux
+// Flags: -m -n
+//
+
+gczeal(2);
+var g1 = newGlobal('same-compartment');
+var proxyStr = "Proxy.create(                                    "+
+"  { getOwnPropertyDescriptor: function() assertEq(true,false),  "+
+"    fix: function() assertEq(true,false), },                    "+
+"  Object.prototype                                              "+
+");                                                              ";
+var proxy1 = g1.eval(proxyStr);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug700295.js
@@ -0,0 +1,18 @@
+// Binary: cache/js-dbg-64-1210706b4576-linux
+// Flags:
+//
+
+this.__proto__ = null;
+Object.prototype.__proto__ = this;
+function exploreProperties(obj) {
+  var props = [];
+  for (var o = obj; o; o = Object.getPrototypeOf(o)) {
+    props = props.concat(Object.getOwnPropertyNames(o));
+  }
+  for (var i = 0; i < props.length; ++i) {
+    var p = props[i];
+    var v = obj[p];
+  }
+}
+var c = [{}];
+exploreProperties(c);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug701332.js
@@ -0,0 +1,15 @@
+// |jit-test| error:InternalError; slow;
+
+// Binary: cache/js-dbg-64-c60535115ea1-linux
+// Flags:
+//
+
+gczeal(2);
+test();
+function test() {
+  function t(o, proplist) {
+    var props=proplist.split(/\s+/g);
+  };
+  t({ bar: 123, baz: 123, quux: 123 }, 'bar baz quux');
+  ( test(), this )(( "7.4.2-6-n" ) , actual, summary + ' : nonjit');
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug704136.js
@@ -0,0 +1,8 @@
+// |jit-test| error:ReferenceError
+
+// Binary: cache/js-dbg-64-a335853be219-linux
+// Flags:
+//
+
+gczeal(4);
+jsTestDriverEnd();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug719686.js
@@ -0,0 +1,32 @@
+// |jit-test| slow;
+
+// Binary: cache/js-dbg-32-e5e66f40c35b-linux
+// Flags:
+//
+
+gczeal(2);
+function subset(list, size) {
+  if (size == 0 || !list.length)
+    return [list.slice(0, 0)];
+  var result = [];
+  for (var i = 0, n = list.length; i < n; i++) {
+    var pick = list.slice(i, i+1);
+    var rest = list.slice(0, i).concat(list.slice(i+1));
+    for each (var x in subset(rest, size-1))
+      result.push(pick.concat(x));
+  }
+  return result;
+}
+var bops = [
+  ["=", "|=", "^=", "&=", "<<=", ">>=", ">>>=", "+=", "-=", "*=", "/=", "%="],
+  ];
+var aops = [];
+for (var i = 0; i < bops.length; i++) {
+  for (var j = 0; j < bops[i].length; j++) {
+    var k = bops[i][j];
+    aops.push(k);
+}
+for (i = 2; i < 5; i++) {
+  var sets = subset(aops, i);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug724875.js
@@ -0,0 +1,15 @@
+// Binary: cache/js-dbg-64-c34398f961e7-linux
+// Flags: --ion-eager
+//
+
+var lfcode = new Array();
+lfcode.push("gczeal(4);");
+lfcode.push("");
+while (true) {
+	var file = lfcode.shift();
+	if (file == undefined) { break; }
+        loadFile(file);
+}
+function loadFile(lfVarx) {
+	eval(lfVarx);
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug729571.js
@@ -0,0 +1,42 @@
+// Binary: cache/js-dbg-64-ca97bbcd6b90-linux
+// Flags: --ion-eager
+//
+
+gczeal(4);
+function TestCase(n, d, e, a) {}
+TestCase.prototype.dump = function () {};
+TestCase.prototype.testFailed = (function TestCase_testFailed() {
+	});
+  try  {
+    try    {    }    catch(ex1)    {    }
+  }  catch(ex)  {  }
+  options.initvalues  = {};
+  var optionNames = options().split(',');
+  var optionsframe = {};
+  try  {
+    optionsClear();
+  }  catch(ex)  {  }
+var lfcode = new Array();
+lfcode.push("\
+  try {  } catch (exception) {  }\
+    try {    } catch (exception) {    }\
+    try {    } catch (exception) {    }\
+    try {    } catch (actual) {    }\
+        var props = {};\
+  function test(which) {\
+    var g = newGlobal(\"new-compartment\");\
+    function addDebugger(g, i) {\
+        var dbg = Debugger(g);\
+        dbg.onDebuggerStatement = function (frame) { };\
+    }\
+    for (var i = 0; i < 3; i++) {\
+        addDebugger(g, i);\
+    }\
+    g.eval(\"debugger;\");\
+}\
+for (var j = 0; j < 3; j++) test(j);\
+");
+while (true) {
+	var file = lfcode.shift(); if (file == undefined) { break; }
+	try { evaluate(file); } catch (lfVare) { }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug729797.js
@@ -0,0 +1,15 @@
+// |jit-test| error:InternalError
+
+// Binary: cache/js-dbg-64-5a04fd69aa09-linux
+// Flags: --ion-eager
+//
+
+var patterns = new Array();
+patterns[0] = '';
+test();
+function test() {
+  for (i in patterns) {
+    s = patterns[i];
+    status =(test)(s);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug729886.js
@@ -0,0 +1,12 @@
+// |jit-test| error:ReferenceError
+
+// Binary: cache/js-opt-64-5a04fd69aa09-linux
+// Flags: --ion-eager
+//
+
+function deep1(x) {
+    if (0) {  }
+    else i : dumpStack();
+}
+for (var i = 0; 1; ++i)
+    deep1(i);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug732852.js
@@ -0,0 +1,10 @@
+// |jit-test| error:SyntaxError
+
+// Binary: cache/js-dbg-64-1fd6c40d3852-linux
+// Flags: --ion-eager
+//
+
+var ary = ["\u001Cfoo", "\u001Dfoo", "\u001Efoo", "\u001Ffoo"];
+for (var i in ary) {
+  ary[Number(i)].search("var MYVAR='077';++MYVAR")
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug732855.js
@@ -0,0 +1,69 @@
+// Binary: cache/js-dbg-64-1fd6c40d3852-linux
+// Flags: --ion-eager
+//
+function TestCase(n, d, e, a) {}
+var msPerDay =   86400000;
+var msPerHour =   3600000;
+var now = new Date();
+var TIME_NOW = now.valueOf();
+function DaysInYear( y ) {
+  if ( y % 4 != 0 ) {
+    return 365;
+  }
+    return 366;
+}
+function TimeInYear( y ) {
+  return ( DaysInYear(y) * msPerDay );
+}
+function TimeFromYear( y ) {
+  return ( msPerDay * DayFromYear(y) );
+}
+function DayFromYear( y ) {
+  return ( 365*(y-1970) +
+           Math.floor((y-1601)/400) );
+}
+function InLeapYear( t ) {
+  if ( DaysInYear(YearFromTime(t)) == 365 ) {
+    return 0;
+  }
+  if ( DaysInYear(YearFromTime(t)) == 366 ) {
+  }
+}
+function YearFromTime( t ) {
+  var sign = ( t < 0 ) ? -1 : 1;
+  var year = ( sign < 0 ) ? 1969 : 1970;
+  for ( var timeToTimeZero = t; ;  ) {
+    timeToTimeZero -= sign * TimeInYear(year)
+      if ( sign < 0 ) {
+      } else {
+        if ( sign * timeToTimeZero < 0 ) {
+          break;
+        } else {
+          year += sign;
+        }
+      }
+  }
+  return ( year );
+}
+function WeekDay( t ) {}
+function LocalTZA() {}
+function LocalTime( t ) {
+  var dst_start = GetDSTStart(t);
+}
+function GetFirstSundayInMonth( t, m ) {
+  var leap = InLeapYear(t);
+}
+function GetDSTStart( t ) {
+  return (GetFirstSundayInMonth(t, 2) + 7*msPerDay + 2*msPerHour - LocalTZA());
+}
+var SECTION = "15.9.5.12";
+addTestCase( TIME_NOW );
+function addTestCase( t ) {
+  var start = TimeFromYear(YearFromTime(t));
+  var stop  = TimeFromYear(YearFromTime(t) + 1);
+  for (var d = start; d < stop; d += msPerDay) {
+    new TestCase( SECTION,
+                  WeekDay((LocalTime(d))),
+                  (__lookupGetter__) );
+  }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug732856.js
@@ -0,0 +1,19 @@
+// Binary: cache/js-dbg-64-1fd6c40d3852-linux
+// Flags: --ion-eager
+//
+
+var cnName = 'name';
+var cnNameGetter = function() {this.nameGETS++; return this._name;};
+obj = (new (function  (  )  {  }  )         );
+obj.__defineGetter__(cnName, cnNameGetter);
+function lameFunc(x, y) {
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (obj.name) + (y >> 16) + (lsw >> 16);
+}
+function runSomeTimes(func, iters) {
+    for (var i = 0; i < iters; ++i) {
+        result = func(42, 42);
+    }
+}
+for (var i = 0; i < 11000; ++i)
+    runSomeTimes(lameFunc, 1);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug732857.js
@@ -0,0 +1,30 @@
+// Binary: cache/js-dbg-32-1fd6c40d3852-linux
+// Flags: --ion-eager
+//
+
+function TestCase(n, d, e, a) {};
+  this.__proto__ = [];
+var msPerDay =   86400000;
+var TIME_1900  = -2208988800000;
+function TimeFromYear( y ) {
+  return ( msPerDay * DayFromYear(y) );
+}
+function DayFromYear( y ) {
+  return ( 365*(y-1970) +
+           Math.floor((y-1601)/400) );
+}
+function YearFromTime( t ) {
+  var sign = ( t < 0 ) ? -1 : 1;
+  var year = ( sign < 0 ) ? 1969 : 1970;
+  return ( year );
+}
+var SECTION = "15.9.5.10";
+addTestCase( TIME_1900 );
+function addTestCase( t ) {
+  var start = TimeFromYear(YearFromTime(t));
+  var stop  = TimeFromYear(YearFromTime(t) + 1);
+  for (var d = start; d < stop; d += msPerDay) {
+    new TestCase( SECTION,
+                  (new Date( SECTION   ? "Failed" : prototype +=  "'abc'.search(new RegExp('^'))") ).getDate() );
+  }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug732861.js
@@ -0,0 +1,12 @@
+// |jit-test| error:ReferenceError
+
+// Binary: cache/js-dbg-64-1fd6c40d3852-linux
+// Flags: --ion-eager
+//
+
+j = 0;
+out1:
+for ((exception) = 0; ; j++)
+    if (j == 50)
+        break out1;
+while (dbgeval("[]").proto ? g : 50) {}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug737300.js
@@ -0,0 +1,21 @@
+// |jit-test| error:ReferenceError
+
+// Binary: cache/js-dbg-64-b5b6e6aebb36-linux
+// Flags: --ion-eager
+//
+
+function loopy(p0)
+{
+ var r3 = p0;
+ var r4 = p0;
+ var r6 = p0;
+ var r7 = p0;
+ while (r2) {
+  while (r2) {
+   r5 = r6 & r1;
+   r3 = r4 & r3;
+   r2 = r7;
+  }
+ }
+}
+loopy(0);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug737737.js
@@ -0,0 +1,36 @@
+// Binary: cache/js-dbg-32-e96d5b1f47b8-linux
+// Flags: --ion-eager
+//
+function b(z) {
+  switch (z) {
+  default:
+    primarySandbox = newGlobal("new-compartment")
+  }
+  return function(f, code) {
+    try {
+      evalcx(code, primarySandbox)
+    } catch (e) {}
+  }
+}
+function a(code) {
+  gc();
+  f = Function(code)
+  c(f, code)
+}
+c = b()
+a("\
+  f2 = (function() {\
+    a0 + o2.m;\
+    a2.shift()\
+  });\
+  a2 = new Array;\
+  Object.defineProperty(a2, 0, {\
+    get: f2\
+  });\
+  o2 = {};\
+  a0 = [];\
+  a2.shift();\
+  var x;\
+")
+a("a0 = x")
+a("a2.shift()")
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug739402.js
@@ -0,0 +1,142 @@
+// |jit-test| slow;
+
+// Binary: cache/js-dbg-32-be41973873db-linux
+// Flags: --ion-eager
+//
+function MersenneTwister19937() {
+  N = 624;
+  var M = 397;
+  MATRIX_A = 567483615;
+  UPPER_MASK = 2147483648;
+  var LOWER_MASK = 767;
+  mt = Array();
+  function unsigned32(n1) {
+    return n1 < 0 ? (n1 ^ UPPER_MASK) + UPPER_MASK : n1;
+  }
+  function addition32(n1, n2) {
+    return unsigned32(n1 + n2 & 4294967295);
+  }
+  function multiplication32(n1, n2) {
+    sum = 0;
+    for (i = 0; i < 32; ++i) {
+      if (n1 >> i & 1) {
+        sum = addition32(sum, unsigned32(n2 << i));
+      }
+    }
+    return sum;
+  }
+  this.init_genrand = function() {
+    for (mti = 1; mti < N; mti++) {
+      mt[mti] = addition32(multiplication32(181433253, unsigned32(mt[mti - 1] ^ mt[mti - 1] >>> 30)), mti);
+    }
+  };
+  this.genrand_int32 = function() {
+    mag01 = Array(0, MATRIX_A);
+    if (mti > N) {
+      for (kk = 0; kk < N - M; kk++) {
+        y = unsigned32(mt[kk] & UPPER_MASK | mt[kk + 1] & LOWER_MASK);
+      }
+      for (; kk < N; kk++) {
+        mt[kk] = unsigned32(mt[kk + (M - N)] ^ y >>> 1 ^ mag01[y & 1]);
+      }
+      mti = 0;
+    }
+    y = mt[mti++];
+    return y;
+  };
+}
+(function() {
+  var fuzzMT = new MersenneTwister19937;
+  fuzzSeed = 4;
+  fuzzMT.init_genrand(fuzzSeed);
+  rnd = function(n) {
+    var x = fuzzMT.genrand_int32() * 2.2e-10;
+    return Math.floor(x * n);
+  };
+}());
+
+function rndElt(a) {
+  return a[rnd(a.length)];
+}
+varBinderFor = ["", "t", ""];
+function forLoopHead(d, b, v, reps) {
+  var sInit = rndElt(varBinderFor) + v + "=0";
+  var sCond = v + "<" + reps;
+  sNext = "++" + v;
+  return "for(" + sInit + ";" + sCond + ";" + sNext + ")";
+}
+function makeBranchUnstableLoop(d, b) {
+  var reps = rnd(rnd(9));
+  v = uniqueVarName();
+  var mod = rnd();
+  target = rnd(mod);
+  return "" + forLoopHead(d, b, v, reps) + "{" + "if(" + v + "%" + mod + "==" + target + "){" + makeStatement(d - 2, b) + "}" + "{" + makeStatement(d - 2) + "}" + "}";
+}
+function weighted(wa) {
+  a = [];
+  for (var i = 0; i < wa.length; ++i) {
+    for (var j = 0; j < wa[i].w; ++j) {
+      a.push(wa[i].fun);
+    }
+  }
+  return a;
+}
+statementMakers = weighted([{
+  w: 6,
+  fun: makeBranchUnstableLoop
+}, {}]);
+(function() {
+  builderStatementMakers = weighted([{
+    w: 1,
+    fun: function() {
+      return "gc()";
+    }
+  }, {
+    w: 10,
+    fun: function() {}
+  }]);
+  makeBuilderStatement = function() {
+    return rndElt(builderStatementMakers)();
+  };
+}());
+function uniqueVarName() {
+  for (i = 0; i < 6; ++i) {
+    s = String.fromCharCode(97 + rnd(6));
+  }
+  return s;
+}
+function makeLittleStatement(d) {
+  rnd(0);
+  if (rnd) {
+    rndElt(littleStatementMakers)();
+  }
+}
+littleStatementMakers = [function() {}];
+function testOne() {
+  var code = makeOv(10);
+  tryItOut(code);
+}
+function makeStatement(d, b) {
+  if (rnd(0)) {}
+  if (rnd(2)) {
+    return makeBuilderStatement();
+  }
+  d < 6 && rnd() == 0;
+  if (d < rnd(8)) {
+    return makeLittleStatement();
+  }
+  return rndElt(statementMakers)(d, b);
+}
+function makeOv(d, B) {
+  if (rnd() == 0) {}
+  return "" + makeStatement(d, [""]);
+}
+function tryItOut(code) {
+  try {
+    f = Function(code);
+    f();
+  } catch (r) {}
+}
+for (let aa = 0; aa < 9999; aa++) {
+  testOne();
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug739901.js
@@ -0,0 +1,20 @@
+// Binary: cache/js-dbg-64-940078281bbf-linux
+// Flags: --ion-eager
+//
+function List(l) {
+  this.l = l;
+}
+function f(p) {
+  return g(p.l);
+};
+function g(p) {
+  return !(p instanceof List) ? null : f(p.l);
+};
+list =
+  new List(new List(
+    new List(new List(
+      new List(new List(
+        new List(new List(null))))))))
+for (let i = 0; i < 99999; i++) {
+  g(list);
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug740654.js
@@ -0,0 +1,14 @@
+// |jit-test| error:InternalError
+
+// Binary: cache/js-dbg-32-92fe907ddac8-linux
+// Flags: -m -n
+//
+mjitChunkLimit(31)
+o = {}
+o.valueOf = function() {
+    for (var p in undefined) {
+        a = new Function;
+    }
+    +o;
+};
++o;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug741199.js
@@ -0,0 +1,9 @@
+// Binary: cache/js-dbg-32-e96d5b1f47b8-linux
+// Flags: --ion-eager
+//
+
+var a = new Array(1000 * 100);
+var i = a.length;
+while (i-- != 0) {}
+gc();
+(({ }).break--);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug743071.js
@@ -0,0 +1,51 @@
+// Binary: cache/js-dbg-64-a9a18824b4c1-linux
+// Flags: --ion-eager
+//
+
+{
+  try
+  {
+    try
+    {
+    }
+    catch(ex1)
+    {
+    }
+  }
+  catch(ex)
+  {
+  }
+}
+function optionsClear() {
+  var optionNames = options().split(',');
+  for (var i = 0; i < optionNames.length; i++)
+  {
+    var optionName = optionNames[i];
+    if (optionName &&
+        optionName != "methodjit_always")
+    {
+      options(optionName);
+    }
+  }
+}
+{
+  optionsClear();
+  {
+  }
+}
+function test() {
+  for ( gTc=0; gTc < gTestcases.length; gTc++ ) {
+    try
+    {
+    }
+    catch(e)
+    {
+    }
+  }
+}
+try {
+var g = newGlobal('new-compartment');
+g.eval("(" + function () {
+        dbg = new Debugger(debuggeeGlobal);
+    } + ")();");
+} catch(exc0) {}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug743094.js
@@ -0,0 +1,11 @@
+// |jit-test| error:InternalError
+
+// Binary: cache/js-dbg-32-a9a18824b4c1-linux
+// Flags: --ion-eager
+//
+
+gczeal(2)
+function test() {
+  typeof (new test("1")) != 'function'
+}
+test();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug743096.js
@@ -0,0 +1,14 @@
+// Binary: cache/js-dbg-64-a9a18824b4c1-linux
+// Flags: --ion-eager
+//
+
+try {
+function f() {
+    var obj = {
+        p0:0, p1:1, p2:2, p3:3, p4:4, p5:5, p6:6, p7:7, p8:8, p9:9,
+        p10:0, p11:1, set:2, p13:3, p14:4, p15:5, p16:6, p17:7, p18:8, p19:9,
+        with  : function() { return 42; }
+    };
+}
+    actual = f();
+} catch(exc1) {}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug746376.js
@@ -0,0 +1,70 @@
+// Binary: cache/js-dbg-64-67bf9a4a1f77-linux
+// Flags: --ion-eager
+//
+var callStack = new Array();
+var gTestcases = new Array();
+var gTc = gTestcases.length;
+function TestCase(n, d, e, a) {
+  this.expect = e;
+  this.actual = a;
+  this.passed = getTestCaseResult(e, a);
+  this.reason = '';
+  this.bugnumber = typeof(BUGNUMER) != 'undefined' ? BUGNUMBER : '';
+  this.type = (typeof window == 'undefined' ? 'shell' : 'browser');
+  gTestcases[gTc++] = this;
+}
+function reportCompare (expected, actual, description) {
+  var output = "";
+  if (typeof description == "undefined")
+  if (expected != actual)
+    printStatus ("Expected value '" + toPrinted(expected) +
+                 "' matched actual value '" + toPrinted(actual) + "'");
+  var testcase = new TestCase("unknown-test-name", description, expected, actual);
+  testcase.reason = output;
+    if (testcase.passed)     {    }
+  return testcase.passed;
+}
+function enterFunc (funcName) {
+  var lastFunc = callStack.pop();
+      reportCompare(funcName, lastFunc, "Test driver failure wrong exit function ");
+}
+function getTestCaseResult(expected, actual)
+function getFailedCases() {
+  for ( var i = 0; i < gTestcases.length; i++ ) {}
+};
+function jit(on) {}
+var lfcode = new Array();
+lfcode.push("\
+var summary = 'decompilation of \"let with with\" ';\
+var actual = '';\
+var expect = '';\
+test();\
+function test() {\
+  enterFunc ('test');\
+  gczeal(2);\
+  for (let q = 0; q < 50; ++q) {\
+    new Function('for (var i = 0; i < 5; ++i) { } ')();\
+    var w = 'r'.match(/r/);\
+    new Function('for (var j = 0; j < 1; ++j) { } ')();\
+  }\
+  jit(('Math.log'));\
+  reportCompare(expect, actual, summary);\
+}\
+");
+delete Debugger;
+while (true) {
+	var file = lfcode.shift(); if (file == undefined) { break; }
+	if (file == "evaluate") {
+	} else {
+                loadFile(file);
+	}
+}
+function loadFile(lfVarx) {
+	try {
+		if (lfVarx.substr(-3) == ".js") {
+		} else {
+			evaluate(lfVarx);
+		}
+	} catch (lfVare) {
+	}
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug746377.js
@@ -0,0 +1,14 @@
+// |jit-test| error:InternalError
+
+// Binary: cache/js-dbg-64-67bf9a4a1f77-linux
+// Flags: --ion-eager
+//
+
+var actual = '';
+test();
+function test()
+{
+  a = {x: 1};
+  b = {__proto__: a};
+    print(actual += test(1,2,3,4));
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug746397.js
@@ -0,0 +1,10 @@
+// |jit-test| error:ReferenceError
+
+// Binary: cache/js-dbg-64-67bf9a4a1f77-linux
+// Flags: --ion-eager
+//
+
+(function () {
+  var a = ['x', 'y'];
+  obj.watch(a[+("0")], counter);
+})();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug754712.js
@@ -0,0 +1,47 @@
+// Binary: cache/js-dbg-64-e8de64e7e9fe-linux
+// Flags: --ion-eager
+//
+function printStatus (msg) {}
+function printBugNumber (num) {}
+function reportCompare (expected, actual, description) {
+    printStatus ("Expected value '" + toPrinted(expected) +  "' matched actual value '" + toPrinted(actual) + "'");
+}
+try  {
+  reportCompare(expectCompile, actualCompile,  summary + ': compile actual');
+}   catch(ex)  {  }
+var lfcode = new Array();
+lfcode.push("\
+var bar = {\
+    b: 2,\
+};\
+var results = [];\
+for each (let [key, value] in Iterator(bar))\
+    results.push(key + \":\" + (results(isXMLName(), \"ok\")));\
+var expect = \"a:1;b:2\";\
+");
+lfcode.push("\
+var BUGNUMBER = 244619;\
+var summary = 'Don\\'t Crash';\
+var actual = 'Crash';\
+function f1()\
+  eval.call((enterFunc ('test')), \"var a = 'vodka'\");\
+gczeal(4);\
+reportCompare(expect, actual, summary);\
+");
+while (true) {
+	var file = lfcode.shift(); if (file == undefined) { break; }
+	if (file == "evaluate") {
+	} else {
+                loadFile(file);
+	}
+}
+function loadFile(lfVarx) {
+	try {
+		if (lfVarx.substr(-3) == ".js") {
+			switch (lfRunTypeId) {			}
+		} else {
+			evaluate(lfVarx);
+		}
+	} catch (lfVare) {
+	}
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug754719.js
@@ -0,0 +1,10 @@
+// Binary: cache/js-dbg-64-e8de64e7e9fe-linux
+// Flags:
+//
+
+function TestCase(n, d, e, a) {}
+(function(  )  {
+    for (var i = 0; i < 64; ++i) {
+        switch (~~(TestCase) % 3) {}
+    }
+})();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug755564.js
@@ -0,0 +1,9 @@
+// |jit-test| error:Error
+
+// Binary: cache/js-dbg-64-50177d59c0e1-linux
+// Flags:
+//
+
+var p = new ParallelArray([1,2,3,4,5]);
+var r = p.scatter([0,1,0,3,4], 9, function (a,b) { return a+b; });
+assertEq(r.toString( 5 ? r : 0, gc()) ,[4,2,9,4,5].join(","));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug756236.js
@@ -0,0 +1,14 @@
+// Binary: cache/js-dbg-64-14735b4dbccc-linux
+// Flags: --ion-eager
+//
+
+gczeal(4);
+function startTest() {}
+function TestCase(n, d, e, a)
+    dump = (function () {});
+  if (typeof document != "object" || !document.location.href.match(/jsreftest.html/)) {}
+function writeHeaderToLog( string ) {}
+var SECTION = "11.4.5";
+new TestCase( SECTION,  "var MYVAR= void 0; --MYVAR", NaN, eval("var MYVAR=void 0; --MYVAR") );
+new TestCase( SECTION, "var MYVAR=0;--MYVAR;MYVAR", -1, eval("var MYVAR=0;--MYVAR;MYVAR") );
+new TestCase( SECTION, "var MYVAR=0;--MYVAR;MYVAR", -1, eval("var MYVAR=0;--MYVAR;MYVAR") );
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug757428.js
@@ -0,0 +1,11 @@
+// Binary: cache/js-dbg-64-d80602d38aa8-linux
+// Flags: --ion-eager
+//
+
+function f(o) {
+    var prop = "arguments";
+    f[prop] = f[prop];
+}
+for(var i=0; i > -10; i-- ) {
+    f(f / 16);
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug758164.js
@@ -0,0 +1,6 @@
+// Binary: cache/js-dbg-64-407632130d1b-linux
+// Flags:
+//
+
+gc();
+evaluate("gcslice(0);");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug759306.js
@@ -0,0 +1,20 @@
+// |jit-test| error:InternalError
+
+// Binary: cache/js-dbg-32-4ce3983a43f4-linux
+// Flags:
+//
+
+function assertEq(setter) {
+        if (setter > 10)
+            return {assertEq: 3.3};
+        return {__proto__: assertEq(setter + 1)};
+    }
+function testX() {
+  var x = 2;
+  var local0 = x;
+  return { local0: local0 };
+}
+var resultsX = testX();
+assertEq(resultsX.local0, 2);
+gczeal(2);
+assertEq(new (Proxy.createFunction({}, function(){}, function(){})), undefined);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug759312.js
@@ -0,0 +1,60 @@
+// Binary: cache/js-dbg-32-4ce3983a43f4-linux
+// Flags: --ion-eager
+//
+try {
+  gczeal(2);
+var MyMath = {
+  random: function() {
+    this.seed = ((this.seed + 0x7ed55d16) + (this.seed << 12))  & 0xffffffff;
+    return (this.seed & 0xfffffff) / 0x10000000;
+  },
+};
+var kSplayTreeSize = 8000;
+var kSplayTreePayloadDepth = 5;
+function GeneratePayloadTree(depth, key) {
+  if (depth == 0) {
+    return {
+      array  : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
+      string : 'String for key ' + key + ' in leaf node'
+    };
+  } else {
+    return {
+      left:  GeneratePayloadTree(depth - 1, key),
+      right: GeneratePayloadTree(depth - 1, key)
+    };
+  }
+}
+function GenerateKey() {
+  return MyMath.random();
+}
+function InsertNewNode() {
+  do {
+    key = GenerateKey();
+  } while (splayTree.find(key) != null);
+  splayTree.insert(key, GeneratePayloadTree(kSplayTreePayloadDepth, key));
+}
+function SplaySetup() {
+  splayTree = new SplayTree();
+  for (var i = 0; i < kSplayTreeSize; i++) InsertNewNode();
+}
+function SplayTree() {
+};
+SplayTree.prototype.isEmpty = function() {
+  return !this.root_;
+};
+SplayTree.prototype.insert = function(key, value) {
+  if (this.isEmpty()) {
+    this.root_ = new SplayTree.Node(key, value);
+  }
+  var node = new SplayTree.Node(key, value);
+  if (key > this.root_.key) {
+    this.root_.left = null;
+  }
+  this.root_ = node;
+};
+SplayTree.prototype.find = function(key) {};
+SplayTree.Node = function(key, value) {
+  this.key = key;
+};
+SplaySetup();
+} catch(exc1) {}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug763039.js
@@ -0,0 +1,69 @@
+// Binary: cache/js-dbg-32-5cfb73435e06-linux
+// Flags: --ion-eager
+//
+var actual = '';
+function TestCase(n, d, e, a) {
+  this.reason = '';
+}
+function inSection(x) {}
+function reportCompare (expected, actual, description) {
+  var testcase = new TestCase("unknown-test-name", description, expected, actual);
+  testcase.reason = output;
+}
+var lfcode = new Array();
+lfcode.push("4");
+lfcode.push("function START(summary) {\
+}\
+function TEST(section, expected, actual) {\
+    return reportCompare(expected, actual, inSection(section) + SUMMARY);\
+}\
+var expect = (1);\
+TEST(1,1 << this <  assertEq++ < this, actual);\
+");
+lfcode.push("\
+gczeal(4);\
+data >>>=  RunSingleBenchmark(data);\
+");
+lfcode.push("4");
+lfcode.push("\
+var BUGNUMBER = 345855;\
+var summary = 'Blank yield expressions are not syntax errors';\
+test();\
+function test() {\
+  try  {\
+    eval('(function() {x = 12 + yield;})');\
+  }  catch(ex)  {}\
+  try  { eval('(function() {x = 12 + yield 42})'); }  catch(ex)  {\
+    status = inSection(4);\
+  }\
+  try  {\
+    eval('(function() {x = 12 + (yield);})');\
+  }  catch(ex)  {  }\
+  try  {\
+    eval('(function () {foo((yield))})');\
+  }  catch(ex)  {  }\
+  try  {\
+    eval('(function() {x = 12 + (yield 42)})');\
+  }  catch(ex)  {  }\
+  reportCompare(expect, actual, summary + ': function() {x = 12 + (yield 42)}');\
+}\
+");
+while (true) {
+	var file = lfcode.shift(); if (file == undefined) { break; }
+                loadFile(file);
+}
+function loadFile(lfVarx) {
+	try {
+		if (lfVarx.substr(-3) == ".js") {
+		} else if (!isNaN(lfVarx)) {
+			lfRunTypeId = lfVarx;
+		} else {
+			switch (lfRunTypeId) {
+				case 1: eval(read(lfVarx)); break;
+				default: evaluate(lfVarx);
+			}
+		}
+	} catch (lfVare) {
+		print(lfVare);
+	}
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug763989.js
@@ -0,0 +1,47 @@
+// Binary: cache/js-dbg-32-4bcbb63b89c3-linux
+// Flags: --ion-eager
+//
+var summary = '';
+function reportFailure (msg) {}
+function toPrinted(value) {
+  value = value.replace(/\n/g, 'NL')
+}
+function reportCompare (expected, actual, description) {
+  var output = "";
+  output += "Expected value '" + toPrinted(expected) +
+      "', Actual value '" + toPrinted(actual) + "' ";
+      reportFailure (description + " : " + output);
+}
+var lfcode = new Array();
+lfcode.push("\
+  expect = actual = 'No Exception';\
+  reportCompare(expect, actual, summary);\
+");
+lfcode.push("\
+function reportFailure (section, msg)\
+  msg = inSection(section)+\"\"+msg;\
+");
+lfcode.push("\
+try {\
+  for (var i in expect) \
+    reportCompare(expect[i], actual[i], getStatus(i));\
+} catch(exc1) {}\
+function getStatus(i) {}\
+");
+lfcode.push("gczeal(2,(9));");
+lfcode.push("evaluate(\"reportCompare(expect, actual, summary);\");");
+	gcPreserveCode()
+while (true) {
+	var file = lfcode.shift(); if (file == undefined) { break; }
+	if (file == "evaluate") {
+	} else {
+                loadFile(file);
+	}
+}
+function loadFile(lfVarx) {
+	try {
+		if (lfVarx.substr(-3) != ".js") {
+			evaluate(lfVarx);
+		}
+	} catch (lfVare) {}
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug764850.js
@@ -0,0 +1,6 @@
+// Binary: cache/js-dbg-64-7ab88528503e-linux
+// Flags:
+//
+
+gczeal(4);
+it.customNative = assertEq;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug765483.js
@@ -0,0 +1,13 @@
+// |jit-test| debug; error:ReferenceError;
+
+// Binary: cache/js-dbg-64-de23a9fc29db-linux
+// Flags: --ion-eager
+//
+
+var obj1 = {}, obj2 = {};
+obj2['b'+i] = 0;
+for (var k in obj2) {
+  (function g() { evalInFrame(1, "assertStackIs(['eval-code', f, 'bound(f)', 'global-code'])", true); })();
+}
+for (var i = 0; i != array.length; ++i)
+  array[i]();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug767679.js
@@ -0,0 +1,10 @@
+// Binary: cache/js-dbg-32-05a756967f25-linux
+// Flags: --ion-eager
+//
+eval("\
+    \"use strict\";\
+    a();\
+    function a() {\
+        print\
+    }\
+")
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug771157.js
@@ -0,0 +1,30 @@
+// Binary: cache/js-dbg-64-9cf3ea112635-linux
+// Flags: --ion-eager
+//
+
+var callStack = new Array();
+function TestCase(n, d, e, a) {
+  this.expect = e;
+  this.actual = a;
+  this.passed = getTestCaseResult(e, a);
+  dump(+ this.path + ' ' + 'reason: ' + toPrinted(this.reason)+ '\n');
+};
+function reportCompare (expected, actual, description) {
+  var testcase = new TestCase("unknown-test-name", description, expected, actual);
+}
+function enterFunc (funcName) {
+  callStack.push(funcName);
+  var lastFunc = callStack.pop();
+  reportCompare(funcName, lastFunc, "Test driver failure wrong exit function ");
+}
+try {
+var summary = 'String static methods';
+var actual = '';
+expect = '2';
+reportCompare(expect, actual, summary + " String.toUpperCase(new Boolean(true))");
+} catch(exc0) {}
+try {
+function TestCase(n, d, e, a) {}
+enterFunc ('test');
+reportCompare(expect, actual, summary);
+} catch(exc2) {}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug779390.js
@@ -0,0 +1,15 @@
+// Binary: cache/js-dbg-64-b46621aba6fd-linux
+// Flags: --ion-eager
+//
+
+function TestCase(n, d, e, a) {
+  this.passed = getTestCaseResult(e, a);
+}
+function getTestCaseResult(expected, actual) {}
+try {
+for (var i = 0; i < bomchars.length; i++)
+  try {} catch(ex) {}
+} catch(exc0) {}
+["a"].map(function(s) {gczeal(4);})[0]
+new TestCase();
+new TestCase("", "", 5e-324, i);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug779818.js
@@ -0,0 +1,12 @@
+// Binary: cache/js-dbg-64-2169bca0c9a5-linux
+// Flags: --ion-eager
+//
+
+var SECTION = "lexical-015";
+(function() {
+    for (var a = 0; a < 9; a++) {
+        if (SECTION[a]) {
+            while (arguments[a]) break;
+        }
+    }
+})()
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug780003.js
@@ -0,0 +1,6 @@
+// |jit-test| error:ReferenceError
+
+// Binary: cache/js-dbg-64-9f3dc298e25b-linux
+// Flags: --ion-eager
+//
+for(a in b){}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug781364.js
@@ -0,0 +1,34 @@
+// Binary: cache/js-dbg-64-21b4797e4cb3-linux
+// Flags: -m -a --ion-eager
+//
+k = m
+function h() {
+  switch (true) {
+  default:
+    x = newGlobal('')
+  }
+  return function(f, code) {
+    try {
+      evalcx(code, x)
+    } catch (e) {}
+  }
+}
+function m() {
+  f()
+}
+function g(code) {
+  f = new Function(code);
+  k(f, code)
+}
+g("k=h()")
+g("\
+    a='';\
+    Object.defineProperty(this,\"b\",{get:function(){a=this.d()}});\
+    Object.defineProperty(this,\"c\",{get:function(){b}});\
+    d=2;\
+    b\
+");
+g("b");
+g("b");
+g("for(v of c);");
+g("a=eval(\"function f(){}\");b")
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug782083.js
@@ -0,0 +1,16 @@
+// Binary: cache/js-dbg-32-f1764bf06b29-linux
+// Flags: --ion-eager
+//
+
+gcPreserveCode();
+function r() {}
+gczeal(2);
+evaluate("");
+evaluate("\
+function randomFloat () {\
+    if (r < 0.25)\
+        fac = 10000000;\
+}\
+for (var i = 0; i < 100000; i++)\
+    randomFloat();\
+");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug782129.js
@@ -0,0 +1,24 @@
+// Binary: cache/js-dbg-32-f1764bf06b29-linux
+// Flags: --ion-eager
+//
+
+var callStack = new Array();
+function enterFunc (funcName) {
+  funcName += "()";
+  callStack.push(funcName);
+}
+function exitFunc (funcName) {
+  var lastFunc = callStack.pop();
+  funcName += "()";
+  if (lastFunc != funcName)
+    print();
+}
+try {
+  test();
+} catch(exc1) {}
+function test() {
+  enterFunc ('test');
+  test();
+}
+for (var l = 0; l < 50000; l++)
+  exitFunc ('test');
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug786106.js
@@ -0,0 +1,6 @@
+// Binary: cache/js-dbg-64-92b9b2840a79-linux
+// Flags:
+//
+
+    var p = new ParallelArray([2, 3,, 4, 5, 6]);
+    var r = p.scatter([0,1,0,3,4], 9, function (a,b) { return a+b; });
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug827821.js
@@ -0,0 +1,36 @@
+// Binary: cache/js-dbg-32-795632f0e4fe-linux
+// Flags: --ion-eager
+//
+
+var lfcode = new Array();
+lfcode.push("3");
+lfcode.push("\
+	gczeal(2);\
+	for (let q = 0; q < 50; ++q) {\
+		var w = \"r\".match(/r/);\
+	}\
+	let (eval) (function  (a) {\
+		Function = gczeal;\
+	})();\
+	// .js\
+");
+lfcode.push(" // .js");
+lfcode.push(" // .js");
+lfcode.push(" // .js");
+while (true) {
+	var file = lfcode.shift(); if (file == undefined) { break; }
+        loadFile(file)
+}
+function loadFile(lfVarx) {
+    try {
+        if (lfVarx.substr(-3) == ".js") {
+	    uneval("foo");
+            switch (lfRunTypeId) {
+                case 3: function newFunc(x) { new Function(x)(); }; newFunc(lfVarx); break;
+                case 4: eval("(function() { " + lfVarx + " })();"); break;
+            }
+        } else if (!isNaN(lfVarx)) {
+            lfRunTypeId = parseInt(lfVarx);
+	}
+    } catch (lfVare) {}
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug829795.js
@@ -0,0 +1,10 @@
+// |jit-test| error:TypeError
+
+// Binary: cache/js-dbg-64-44dcffe8792b-linux
+// Flags: -a
+//
+try {
+    x = [];
+    Array.prototype.forEach()
+} catch (e) {}
+x.forEach()
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug829813.js
@@ -0,0 +1,8 @@
+// Binary: cache/js-dbg-64-44dcffe8792b-linux
+// Flags:
+//
+for (x in [0]) {
+    (function() {
+        return Object.propertyIsEnumerable
+    })().call([0], x)
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug830049.js
@@ -0,0 +1,14 @@
+// |jit-test| error:InternalError
+
+// Binary: cache/js-dbg-64-1761f4a9081c-linux
+// Flags: --ion-eager
+//
+
+p = Proxy.create({
+  has: function() function r() s += ''
+})
+Object.prototype.__proto__ = p
+function TestCase(n) {
+    this.name = n
+}
+new TestCase()
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2389,21 +2389,21 @@ JS_strdup(JSContext *cx, const char *s);
  * JS_AddGCThingRoot takes a pointer to a JSObject * or JString *.
  *
  * Note that, since JS_Add*Root stores the address of a variable (of type
  * jsval, JSString *, or JSObject *), that variable must live until
  * JS_Remove*Root is called to remove that variable. For example, after:
  *
  *   void some_function() {
  *     jsval v;
- *     JS_AddNamedRootedValue(cx, &v, "name");
+ *     JS_AddNamedValueRoot(cx, &v, "name");
  *
  * the caller must perform
  *
- *     JS_RemoveRootedValue(cx, &v);
+ *     JS_RemoveValueRoot(cx, &v);
  *
  * before some_function() returns.
  *
  * Also, use JS_AddNamed*Root(cx, &structPtr->memberObj, "structPtr->memberObj")
  * in preference to JS_Add*Root(cx, &structPtr->memberObj), in order to identify
  * roots by their source callsites.  This way, you can find the callsite while
  * debugging if you should fail to do JS_Remove*Root(cx, &structPtr->memberObj)
  * before freeing structPtr's memory.
--- a/js/xpconnect/tests/mochitest/test_bug446584.html
+++ b/js/xpconnect/tests/mochitest/test_bug446584.html
@@ -18,18 +18,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 446584 **/
 
 function test(val) {
   try {
     document.createNodeIterator(document.body,
                                 NodeFilter.SHOW_ALL,
-                                function() { throw val },
-                                true).nextNode();
+                                function() { throw val }).nextNode();
     ok(false, "NodeIterator::nextNode() should have thrown an exception.");
   } catch (ex) {
     ok(val === ex, "NodeIterator did not properly forward exception " +
        val + " of type " + typeof val + ".  Thrown value was " + ex + ".");
   }
 }
 
 test(0);
--- a/js/xpconnect/tests/mochitest/test_bug502959.html
+++ b/js/xpconnect/tests/mochitest/test_bug502959.html
@@ -18,17 +18,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script type="application/javascript">
 
 /** Test for Bug 502959 **/
 // Whatever you do don't use the word "wrapped" in this function.
 function foo() {
   ok(true, "Able to call the function");
 }
 
-var iter = document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, foo, false);
+var iter = document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, foo);
 var doublewrapped = iter.filter;
 
 ok(doublewrapped.toString().indexOf("wrapped") > 0, "got a double-wrapped object back");
 
 (function () {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     Components.utils.forceGC();
 })();
--- a/js/xpconnect/tests/mochitest/test_bug505915.html
+++ b/js/xpconnect/tests/mochitest/test_bug505915.html
@@ -18,17 +18,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script type="application/javascript;version=1.7">
 
 /** Test for Bug 505915 **/
 window.addEventListener("message", function () { gen.next() }, false);
 
 function go() {
     var ifr = $('ifr');
     try {
-        document.createTreeWalker(ifr.contentDocument, 0, null, false);
+        document.createTreeWalker(ifr.contentDocument, 0, null);
         ok(false, "should have thrown a security exception");
     } catch (e) {
         ok(/NS_ERROR_XPC_SECURITY_MANAGER_VETO/.test(e) ||
            /TypeError: Value does not implement interface Node/.test(e),
            "threw a security exception or binding exception instead of an " +
            "invalid child exception");
     }
 
--- a/layout/base/nsPresArena.cpp
+++ b/layout/base/nsPresArena.cpp
@@ -19,31 +19,19 @@
 #include "nsServiceManagerUtils.h"
 #include "nsPrintfCString.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsICrashReporter.h"
 #endif
 
 #include "mozilla/StandardInteger.h"
+#include "mozilla/ASan.h"
 
-#if defined(MOZ_ASAN)
-// XXX These come from sanitizer/asan_interface.h but that header doesn't seem
-// to be installed by default?
-extern "C" {
-  void __asan_poison_memory_region(void const volatile *addr, size_t size)
-    __attribute__((visibility("default")));
-  void __asan_unpoison_memory_region(void const volatile *addr, size_t size)
-    __attribute__((visibility("default")));
-#define ASAN_POISON_MEMORY_REGION(addr, size)   \
-  __asan_poison_memory_region((addr), (size))
-#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
-  __asan_unpoison_memory_region((addr), (size))
-}
-#elif defined(MOZ_VALGRIND)
+#if defined(MOZ_VALGRIND)
 #include "valgrind/memcheck.h"
 #endif
 
 // Even on 32-bit systems, we allocate objects from the frame arena
 // that require 8-byte alignment.  The cast to uintptr_t is needed
 // because plarena isn't as careful about mask construction as it
 // ought to be.
 #define ALIGN_SHIFT 3
--- a/layout/reftests/svg/as-image/reftest.list
+++ b/layout/reftests/svg/as-image/reftest.list
@@ -129,18 +129,18 @@ skip-if(B2G) == list-simple-1.html list-
 skip-if(B2G) == svg-image-script-1.svg lime100x100.svg # bug 773482
 == svg-image-script-2.svg lime100x100.svg
 
 # tests for external resources vs. data URIs in SVG as an image
 == svg-image-datauri-1.html            lime100x100.svg
 HTTP == svg-image-datauri-1.html       lime100x100.svg
 == svg-image-external-1.html           blue100x100.svg
 HTTP == svg-image-external-1.html      blue100x100.svg
-skip-if(B2G) == svg-stylesheet-datauri-1.html       lime100x100.svg
-skip-if(B2G) HTTP == svg-stylesheet-datauri-1.html  lime100x100.svg
+random skip-if(B2G) == svg-stylesheet-datauri-1.html       lime100x100.svg
+random skip-if(B2G) HTTP == svg-stylesheet-datauri-1.html  lime100x100.svg
 == svg-stylesheet-external-1.html      blue100x100.svg
 HTTP == svg-stylesheet-external-1.html blue100x100.svg
 
 # test that :visited status is ignored in image documents
 # We load the images directly first, to be sure history is populated.
 # It's also good to verify that the helper images don't match lime100x100.svg
 # in non-image contexts, but for that to work, we have to reliably count on
 # :visited styles loading (asynchronously), so we test that in
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -2008,17 +2008,26 @@ nsCSSKeyframeRule::Clone() const
 {
   nsRefPtr<css::Rule> clone = new nsCSSKeyframeRule(*this);
   return clone.forget();
 }
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeRule)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeRule)
 
-NS_IMPL_CYCLE_COLLECTION_1(nsCSSKeyframeRule, mDOMDeclaration);
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSKeyframeRule)
+  if (tmp->mDOMDeclaration) {
+    tmp->mDOMDeclaration->DropReference();
+    ImplCycleCollectionUnlink(tmp->mDOMDeclaration);
+  }
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSKeyframeRule)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 DOMCI_DATA(MozCSSKeyframeRule, nsCSSKeyframeRule)
 
 // QueryInterface implementation for nsCSSKeyframeRule
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeRule)
   NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozCSSKeyframeRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
--- a/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py
+++ b/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py
@@ -367,17 +367,17 @@ class MakefileGenerator(object):
       return False
     if self.flavor == 'win':
       top = self.relative_topsrcdir
     else:
       top = self.topsrcdir
     WriteMakefile(output_file, data, build_file, depth, top,
                   # we set srcdir up one directory, since the subdir
                   # doesn't actually exist in the source directory
-                  swapslashes(os.path.join(top, self.relative_srcdir, os.path.split(rel_path)[0])),
+                  swapslashes(os.path.normpath(os.path.join(top, self.relative_srcdir, os.path.split(rel_path)[0]))),
                   self.relative_srcdir,
                   self.common_mk_path)
     return True
 
 def GenerateOutput(target_list, target_dicts, data, params):
   options = params['options']
   flavor = GetFlavor(params)
   generator_flags = params.get('generator_flags', {})
new file mode 100644
--- /dev/null
+++ b/mfbt/ASan.h
@@ -0,0 +1,27 @@
+/* -*- 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/. */
+
+/*
+ * Provides ASan (AddressSanitizer) specific functions that are normally
+ * provided through the sanitizer/asan_interface.h header installed by ASan.
+ */
+
+#ifndef mozilla_ASan_h_
+#define mozilla_ASan_h_
+
+#ifdef MOZ_ASAN
+extern "C" {
+  void __asan_poison_memory_region(void const volatile *addr, size_t size)
+    __attribute__((visibility("default")));
+  void __asan_unpoison_memory_region(void const volatile *addr, size_t size)
+    __attribute__((visibility("default")));
+#define ASAN_POISON_MEMORY_REGION(addr, size)   \
+  __asan_poison_memory_region((addr), (size))
+#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
+  __asan_unpoison_memory_region((addr), (size))
+}
+#endif
+
+#endif  /* mozilla_ASan_h_ */
--- a/mfbt/exported_headers.mk
+++ b/mfbt/exported_headers.mk
@@ -4,16 +4,17 @@
 
 # This file defines the headers exported by mfbt.  It is included by mfbt
 # itself and by the JS engine, which, when built standalone, must install
 # mfbt's exported headers itself.
 
 EXPORTS_NAMESPACES += mozilla
 
 EXPORTS_mozilla += \
+  ASan.h \
   Assertions.h \
   Attributes.h \
   BloomFilter.h \
   Char16.h \
   CheckedInt.h \
   Compiler.h \
   Constants.h \
   DebugOnly.h \
--- a/mobile/android/base/TabsTray.java
+++ b/mobile/android/base/TabsTray.java
@@ -343,17 +343,18 @@ public class TabsTray extends ListView
 
         private int mListWidth = 1;
 
         private View mSwipeView;
         private AnimatorProxy mSwipeProxy;
         private int mSwipeViewPosition;
         private Runnable mPendingCheckForTap;
 
-        private float mSwipeStart;
+        private float mSwipeStartX;
+        private float mSwipeStartY;
         private boolean mSwiping;
         private boolean mEnabled;
 
         public TabSwipeGestureListener() {
             mSwipeView = null;
             mSwipeProxy = null;
             mSwipeViewPosition = ListView.INVALID_POSITION;
             mSwiping = false;
@@ -395,17 +396,18 @@ public class TabsTray extends ListView
                     // Check if we should set pressed state on the
                     // touched view after a standard delay.
                     triggerCheckForTap();
 
                     // Find out which view is being touched
                     mSwipeView = findViewAt(e.getRawX(), e.getRawY());
 
                     if (mSwipeView != null) {
-                        mSwipeStart = e.getRawX();
+                        mSwipeStartX = e.getRawX();
+                        mSwipeStartY = e.getRawY();
                         mSwipeViewPosition = TabsTray.this.getPositionForView(mSwipeView);
 
                         mVelocityTracker = VelocityTracker.obtain();
                         mVelocityTracker.addMovement(e);
                     }
 
                     view.onTouchEvent(e);
                     return true;
@@ -450,30 +452,40 @@ public class TabsTray extends ListView
                     else
                         animateCancel(mSwipeView);
 
                     mVelocityTracker = null;
                     mSwipeView = null;
                     mSwipeViewPosition = ListView.INVALID_POSITION;
                     mSwipeProxy = null;
 
-                    mSwipeStart = 0;
+                    mSwipeStartX = 0;
+                    mSwipeStartY = 0;
                     mSwiping = false;
 
                     break;
                 }
 
                 case MotionEvent.ACTION_MOVE: {
                     if (mSwipeView == null)
                         break;
 
                     mVelocityTracker.addMovement(e);
 
-                    float deltaX = e.getRawX() - mSwipeStart;
-                    if (Math.abs(deltaX) > mSwipeThreshold) {
+                    float deltaX = e.getRawX() - mSwipeStartX;
+                    float deltaY = e.getRawY() - mSwipeStartY;
+                    boolean isScrollingX = Math.abs(deltaX) > mSwipeThreshold;
+                    boolean isScrollingY = Math.abs(deltaY) > mSwipeThreshold;
+
+                    // If we're actually swiping, make sure we don't
+                    // set pressed state on the swiped view.
+                    if (isScrollingX || isScrollingY)
+                        cancelCheckForTap();
+
+                    if (isScrollingX) {
                         // If we're actually swiping, make sure we don't
                         // set pressed state on the swiped view.
                         cancelCheckForTap();
 
                         mSwiping = true;
                         TabsTray.this.requestDisallowInterceptTouchEvent(true);
 
                         // Stops listview from highlighting the touched item
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -205,16 +205,19 @@
 @BINPATH@/components/profiler.xpt
 #endif
 @BINPATH@/components/proxyObject.xpt
 @BINPATH@/components/rdf.xpt
 @BINPATH@/components/satchel.xpt
 @BINPATH@/components/saxparser.xpt
 @BINPATH@/components/sessionstore.xpt
 @BINPATH@/components/services-crypto-component.xpt
+#ifdef MOZ_SERVICES_CAPTIVEDETECT
+@BINPATH@/components/services-captivedetect.xpt
+#endif
 @BINPATH@/components/shellservice.xpt
 @BINPATH@/components/shistory.xpt
 @BINPATH@/components/spellchecker.xpt
 @BINPATH@/components/storage.xpt
 @BINPATH@/components/telemetry.xpt
 @BINPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @BINPATH@/components/toolkitremote.xpt
@@ -372,16 +375,21 @@
 @BINPATH@/components/PeerConnection.manifest
 #endif
 
 #ifdef MOZ_SERVICES_HEALTHREPORT
 @BINPATH@/components/HealthReportComponents.manifest
 @BINPATH@/components/HealthReportService.js
 #endif
 
+#ifdef MOZ_SERVICES_CAPTIVEDETECT
+@BINPATH@/components/CaptivePortalDetectComponents.manifest
+@BINPATH@/components/captivedetect.js
+#endif
+
 ; Modules
 @BINPATH@/modules/*
 
 #ifdef MOZ_SAFE_BROWSING
 ; Safe Browsing
 @BINPATH@/components/nsURLClassifier.manifest
 @BINPATH@/components/nsUrlClassifierHashCompleter.js
 @BINPATH@/components/nsUrlClassifierListManager.js
@@ -423,16 +431,20 @@
 @BINPATH@/@PREF_DIR@/mobile.js
 @BINPATH@/@PREF_DIR@/mobile-branding.js
 @BINPATH@/@PREF_DIR@/channel-prefs.js
 @BINPATH@/greprefs.js
 @BINPATH@/defaults/autoconfig/platform.js
 @BINPATH@/defaults/autoconfig/prefcalls.js
 @BINPATH@/defaults/profile/prefs.js
 
+#ifdef MOZ_SERVICES_CAPTIVEDETECT
+@BINPATH@/defaults/pref/services-captivedetect.js
+#endif
+
 ; [Layout Engine Resources]
 ; Style Sheets, Graphics and other Resources used by the layout engine. 
 @BINPATH@/res/EditorOverride.css
 @BINPATH@/res/contenteditable.css
 @BINPATH@/res/designmode.css
 @BINPATH@/res/TopLevelImageDocument.css
 @BINPATH@/res/TopLevelVideoDocument.css
 @BINPATH@/res/table-add-column-after-active.gif
--- a/mobile/xul/chrome/content/browser.js
+++ b/mobile/xul/chrome/content/browser.js
@@ -2705,17 +2705,17 @@ function importDialog(aParent, aSrc, aAr
   let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
   xhr.open("GET", aSrc, false);
   xhr.overrideMimeType("text/xml");
   xhr.send(null);
   if (!xhr.responseXML)
     return null;
 
   let currentNode;
-  let nodeIterator = xhr.responseXML.createNodeIterator(xhr.responseXML, NodeFilter.SHOW_TEXT, null, false);
+  let nodeIterator = xhr.responseXML.createNodeIterator(xhr.responseXML, NodeFilter.SHOW_TEXT, null);
   while (currentNode = nodeIterator.nextNode()) {
     let trimmed = currentNode.nodeValue.replace(/^\s\s*/, "").replace(/\s\s*$/, "");
     if (!trimmed.length)
       currentNode.parentNode.removeChild(currentNode);
   }
 
   let doc = xhr.responseXML.documentElement;
 
--- a/netwerk/sctp/datachannel/DataChannel.cpp
+++ b/netwerk/sctp/datachannel/DataChannel.cpp
@@ -995,17 +995,17 @@ DataChannelConnection::SendDeferredMessa
         uint32_t len               = channel->mBufferedData[0]->mLength;
 
         // SCTP will return EMSGSIZE if the message is bigger than the buffer
         // size (or EAGAIN if there isn't space)
         if ((result = usrsctp_sendv(mSocket, data, len,
                                     nullptr, 0,
                                     (void *)spa, (socklen_t)sizeof(struct sctp_sendv_spa),
                                     SCTP_SENDV_SPA,
-                                    spa->sendv_sndinfo.snd_flags) < 0)) {
+                                    0) < 0)) {
           if (errno == EAGAIN || errno == EWOULDBLOCK) {
             // leave queued for resend
             failed_send = true;
             LOG(("queue full again when resending %d bytes (%d)", len, result));
           } else {
             LOG(("error %d re-sending string", errno));
             failed_send = true;
           }
@@ -1861,17 +1861,17 @@ DataChannelConnection::OpenFinish(alread
   nsRefPtr<DataChannel> channel(aChannel);
 
   mLock.AssertCurrentThreadOwns();
 
   LOG(("Finishing open: channel %p, streamOut = %u", channel.get(), streamOut));
 
   if (streamOut == INVALID_STREAM) {
     if (!RequestMoreStreamsOut()) {
-      if (channel->mFlags &= DATA_CHANNEL_FLAGS_FINISH_OPEN) {
+      if (channel->mFlags & DATA_CHANNEL_FLAGS_FINISH_OPEN) {
         // We already returned the channel to the app.  Mark it closed
         channel->mState = CLOSED;
         NS_ERROR("Failed to request more streams");
         return channel.forget();
       }
       // we can do this with the lock held because mStreamOut is INVALID_STREAM,
       // so there's no outbound channel to reset
       return nullptr;
@@ -1925,34 +1925,36 @@ DataChannelConnection::SendMsgInternal(D
   if (channel->mState == CONNECTING) {
     flags &= ~SCTP_UNORDERED;
   }
   spa.sendv_sndinfo.snd_ppid = htonl(ppid);
   spa.sendv_sndinfo.snd_sid = channel->mStreamOut;
   spa.sendv_sndinfo.snd_flags = flags;
   spa.sendv_sndinfo.snd_context = 0;
   spa.sendv_sndinfo.snd_assoc_id = 0;
+  spa.sendv_flags = SCTP_SEND_SNDINFO_VALID;
 
-  spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_TTL;
-  spa.sendv_prinfo.pr_value = channel->mPrValue;
-
-  spa.sendv_flags = SCTP_SEND_SNDINFO_VALID | SCTP_SEND_PRINFO_VALID;
+  if (channel->mPrPolicy != SCTP_PR_SCTP_NONE) {
+    spa.sendv_prinfo.pr_policy = channel->mPrPolicy;
+    spa.sendv_prinfo.pr_value = channel->mPrValue;
+    spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
+  }
 
   // Note: Main-thread IO, but doesn't block!
   // XXX FIX!  to deal with heavy overruns of JS trying to pass data in
   // (more than the buffersize) queue data onto another thread to do the
   // actual sends.  See netwerk/protocol/websocket/WebSocketChannel.cpp
 
   // SCTP will return EMSGSIZE if the message is bigger than the buffer
   // size (or EAGAIN if there isn't space)
   if (channel->mBufferedData.IsEmpty()) {
     result = usrsctp_sendv(mSocket, data, length,
                            nullptr, 0,
                            (void *)&spa, (socklen_t)sizeof(struct sctp_sendv_spa),
-                           SCTP_SENDV_SPA, flags);
+                           SCTP_SENDV_SPA, 0);
     LOG(("Sent buffer (len=%u), result=%d", length, result));
   } else {
     // Fake EAGAIN if we're already buffering data
     result = -1;
     errno = EAGAIN;
   }
   if (result < 0) {
     if (errno == EAGAIN || errno == EWOULDBLOCK) {
--- a/parser/htmlparser/tests/mochitest/parser_datreader.js
+++ b/parser/htmlparser/tests/mochitest/parser_datreader.js
@@ -95,31 +95,31 @@ function test_parser(testlist) {
 
 /**
  * Transforms a DOM document to a string matching the format in 
  * the test cases.
  *
  * @param the DOM document
  */
 function docToTestOutput(doc) {
-  var walker = doc.createTreeWalker(doc, NodeFilter.SHOW_ALL, null, true);
+  var walker = doc.createTreeWalker(doc, NodeFilter.SHOW_ALL, null);
   return addLevels(walker, "", "| ").slice(0,-1); // remove the last newline
 }
 
 /**
  * Transforms the descendants of an element to a string matching the format
  * in the test cases.
  *
  * @param an element
  */
 function fragmentToTestOutput(elt) {
   var walker = elt.ownerDocument.createTreeWalker(elt, NodeFilter.SHOW_ALL, 
     function (node) { return elt == node ? 
                         NodeFilter.FILTER_SKIP : 
-                        NodeFilter.FILTER_ACCEPT; }, true);
+                        NodeFilter.FILTER_ACCEPT; });
   return addLevels(walker, "", "| ").slice(0,-1); // remove the last newline
 }
 
 function addLevels(walker, buf, indent) {
   if(walker.firstChild()) {
     do {
       buf += indent;
       switch (walker.currentNode.nodeType) {
--- a/python/mozbuild/mozbuild/test/test_mozconfig.py
+++ b/python/mozbuild/mozbuild/test/test_mozconfig.py
@@ -24,16 +24,18 @@ from mozbuild.mozconfig import (
     MozconfigLoader,
 )
 
 
 class TestMozconfigLoader(unittest.TestCase):
     def setUp(self):
         self._old_env = dict(os.environ)
         os.environ.pop('MOZCONFIG', None)
+        os.environ.pop('CC', None)
+        os.environ.pop('CXX', None)
         self._temp_dirs = set()
 
     def tearDown(self):
         os.environ.clear()
         os.environ.update(self._old_env)
 
         for d in self._temp_dirs:
             rmtree(d)
--- a/services/Makefile.in
+++ b/services/Makefile.in
@@ -25,9 +25,13 @@ endif
 ifdef MOZ_SERVICES_METRICS
 PARALLEL_DIRS += metrics
 endif
 
 ifdef MOZ_SERVICES_SYNC
 PARALLEL_DIRS += sync
 endif
 
+ifdef MOZ_SERVICES_CAPTIVEDETECT
+PARALLEL_DIRS += captivedetect
+endif
+
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/services/captivedetect/CaptivePortalDetectComponents.manifest
@@ -0,0 +1,2 @@
+component {d9cd00ba-aa4d-47b1-8792-b1fe0cd35060} captivedetect.js
+contract @mozilla.org/services/captive-detector;1 {d9cd00ba-aa4d-47b1-8792-b1fe0cd35060}
new file mode 100644
--- /dev/null
+++ b/services/captivedetect/Makefile.in
@@ -0,0 +1,27 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH     = @DEPTH@
+topsrcdir = @top_srcdir@
+srcdir    = @srcdir@
+VPATH     = @srcdir@
+relativesrcdir = @relativesrcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE         = services-captivedetect
+XPIDL_MODULE   = services-captivedetect
+
+XPIDLSRCS = \
+  nsICaptivePortalDetector.idl \
+  $(NULL)
+
+EXTRA_COMPONENTS = \
+  CaptivePortalDetectComponents.manifest \
+  captivedetect.js \
+  $(NULL)
+
+PREF_JS_EXPORTS := $(srcdir)/services-captivedetect.js
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/services/captivedetect/captivedetect.js
@@ -0,0 +1,426 @@
+/* -*- Mode: Java; 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/. */
+
+'use strict';
+
+const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+
+const DEBUG = false; // set to true to show debug messages
+
+const kCAPTIVEPORTALDETECTOR_CONTRACTID = '@mozilla.org/services/captive-detector;1';
+const kCAPTIVEPORTALDETECTOR_CID        = Components.ID('{d9cd00ba-aa4d-47b1-8792-b1fe0cd35060}');
+
+const kOpenCaptivePortalLoginEvent = 'captive-portal-login';
+const kAbortCaptivePortalLoginEvent = 'captive-portal-login-abort';
+
+function URLFetcher(url, timeout) {
+  let self = this;
+  let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
+              .createInstance(Ci.nsIXMLHttpRequest);
+  xhr.open('GET', url, true);
+  // Prevent the request from reading from the cache.
+  xhr.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
+  // Prevent the request from writing to the cache.
+  xhr.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
+  // The Cache-Control header is only interpreted by proxies and the
+  // final destination. It does not help if a resource is already
+  // cached locally.
+  xhr.setRequestHeader("Cache-Control", "no-cache");
+  // HTTP/1.0 servers might not implement Cache-Control and
+  // might only implement Pragma: no-cache
+  xhr.setRequestHeader("Pragma", "no-cache");
+
+  xhr.timeout = timeout;
+  xhr.ontimeout = function () { self.ontimeout(); };
+  xhr.onerror = function () { self.onerror(); };
+  xhr.onreadystatechange = function(oEvent) {
+    if (xhr.readyState === 4) {
+      if (self._isAborted) {
+        return;
+      }
+      if (xhr.status === 200) {
+        self.onsuccess(xhr.responseText);
+      } else {
+        self.onredirectorerror(xhr.status);
+      }
+    }
+  };
+  xhr.send();
+  this._xhr = xhr;
+}
+
+URLFetcher.prototype = {
+  _isAborted: false,
+  ontimeout: function() {},
+  onerror: function() {},
+  abort: function() {
+    if (!this._isAborted) {
+      this._isAborted = true;
+      this._xhr.abort();
+    }
+  },
+}
+
+function LoginObserver(captivePortalDetector) {
+  const LOGIN_OBSERVER_STATE_DETACHED = 0; /* Should not monitor network activity since no ongoing login procedure */
+  const LOGIN_OBSERVER_STATE_IDLE = 1; /* No network activity currently, waiting for a longer enough idle period */
+  const LOGIN_OBSERVER_STATE_BURST = 2; /* Network activity is detected, probably caused by a login procedure */
+  const LOGIN_OBSERVER_STATE_VERIFY_NEEDED = 3; /* Verifing network accessiblity is required after a long enough idle */
+  const LOGIN_OBSERVER_STATE_VERIFYING = 4; /* LoginObserver is probing if public network is available */
+
+  let state = LOGIN_OBSERVER_STATE_DETACHED;
+
+  let timer = Cc['@mozilla.org/timer;1'].createInstance(Ci.nsITimer);
+  let activityDistributor = Cc['@mozilla.org/network/http-activity-distributor;1']
+                               .getService(Ci.nsIHttpActivityDistributor);
+  let urlFetcher = null;
+
+  let pageCheckingDone = function pageCheckingDone() {
+    if (state === LOGIN_OBSERVER_STATE_VERIFYING) {
+      urlFetcher = null;
+      // Finish polling the canonical site, switch back to idle state and waiting for next burst
+      state = LOGIN_OBSERVER_STATE_IDLE;
+      timer.initWithCallback(observer,
+                             captivePortalDetector._pollingTime,
+                             timer.TYPE_ONE_SHOT);
+    }
+  };
+
+  let checkPageContent = function checkPageContent() {
+    debug("checking if public network is available after the login procedure");
+
+    urlFetcher = new URLFetcher(captivePortalDetector._canonicalSiteURL,
+                                captivePortalDetector._maxWaitingTime);
+    urlFetcher.ontimeout = pageCheckingDone;
+    urlFetcher.onerror = pageCheckingDone;
+    urlFetcher.onsuccess = function (content) {
+      if (captivePortalDetector.validateContent(content)) {
+        urlFetcher = null;
+        captivePortalDetector.executeCallback(true);
+      } else {
+        pageCheckingDone();
+      }
+    };
+    urlFetcher.onredirectorerror = pageCheckingDone;
+  };
+
+  // Public interface of LoginObserver
+  let observer = {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIHttpActivityOberver,
+                                           Ci.nsITimerCallback]),
+
+    attach: function attach() {
+      if (state === LOGIN_OBSERVER_STATE_DETACHED) {
+        activityDistributor.addObserver(this);
+        state = LOGIN_OBSERVER_STATE_IDLE;
+        timer.initWithCallback(this,
+                               captivePortalDetector._pollingTime,
+                               timer.TYPE_ONE_SHOT);
+        debug('attach HttpObserver for login activity');
+      }
+    },
+
+    detach: function detach() {
+      if (state !== LOGIN_OBSERVER_STATE_DETACHED) {
+        if (urlFetcher) {
+          urlFetcher.abort();
+          urlFetcher = null;
+        }
+        activityDistributor.removeObserver(this);
+        timer.cancel();
+        state = LOGIN_OBSERVER_STATE_DETACHED;
+        debug('detach HttpObserver for login activity');
+      }
+    },
+
+    /*
+     * Treat all HTTP transactions as captive portal login activities.
+     */
+    observeActivity: function observeActivity(aHttpChannel, aActivityType,
+                                              aActivitySubtype, aTimestamp,
+                                              aExtraSizeData, aExtraStringData) {
+      if (aActivityType === Ci.nsIHttpActivityObserver.ACTIVITY_TYPE_HTTP_TRANSACTION
+          && aActivitySubtype === Ci.nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_COMPLETE) {
+        switch (state) {
+          case LOGIN_OBSERVER_STATE_IDLE:
+          case LOGIN_OBSERVER_STATE_VERIFY_NEEDED:
+            state = LOGIN_OBSERVER_STATE_BURST;
+            break;
+          default:
+            break;
+        }
+      }
+    },
+
+    /*
+     * Check if login activity is finished according to HTTP burst.
+     */
+    notify : function notify() {
+      switch(state) {
+        case LOGIN_OBSERVER_STATE_BURST:
+          // Wait while network stays idle for a short period
+          state = LOGIN_OBSERVER_STATE_VERIFY_NEEDED;
+          // Fall though to start polling timer
+        case LOGIN_OBSERVER_STATE_IDLE:
+          timer.initWithCallback(this,
+                                 captivePortalDetector._pollingTime,
+                                 timer.TYPE_ONE_SHOT);
+          break;
+        case LOGIN_OBSERVER_STATE_VERIFY_NEEDED:
+          // Polling the canonical website since network stays idle for a while
+          state = LOGIN_OBSERVER_STATE_VERIFYING;
+          checkPageContent();
+          break;
+
+        default:
+          break;
+      }
+    },
+  };
+
+  return observer;
+}
+
+function CaptivePortalDetector() {
+  // Load preference
+  this._canonicalSiteURL =
+    Services.prefs.getCharPref('services.captivedetect.canonicalURL');
+  this._canonicalSiteExpectedContent =
+    Services.prefs.getCharPref('services.captivedetect.canonicalContent');
+  this._maxWaitingTime =
+    Services.prefs.getIntPref('services.captivedetect.maxWaitingTime');
+  this._pollingTime =
+    Services.prefs.getIntPref('services.captivedetect.pollingTime');
+  this._maxRetryCount =
+    Services.prefs.getIntPref('services.captivedetect.maxRetryCount');
+  debug('Load Prefs {site=' + this._canonicalSiteURL + ',content='
+        + this._canonicalSiteExpectedContent + ',time=' + this._maxWaitingTime
+        + "max-retry=" + this._maxRetryCount + '}');
+
+  // Create HttpObserver for monitoring the login procedure
+  this._loginObserver = LoginObserver(this);
+
+  this._nextRequestId = 0;
+  this._runningRequest = null;
+  this._requestQueue = []; // Maintain a progress table, store callbacks and the ongoing XHR
+  this._interfaceNames = {}; // Maintain names of the requested network interfaces
+
+  debug('CaptiveProtalDetector initiated, waitng for network connection established');
+}
+
+CaptivePortalDetector.prototype = {
+  classID:   kCAPTIVEPORTALDETECTOR_CID,
+  classInfo: XPCOMUtils.generateCI({classID: kCAPTIVEPORTALDETECTOR_CID,
+                                    contractID: kCAPTIVEPORTALDETECTOR_CONTRACTID,
+                                    classDescription: 'Captive Portal Detector',
+                                    interfaces: [Ci.nsICaptivePortalDetector]}),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalDetector]),
+
+  // nsICaptivePortalDetector
+  checkCaptivePortal: function checkCaptivePortal(aInterfaceName, aCallback) {
+    // Prevent multiple requests on a single network interface
+    if (this._interfaceNames[aInterfaceName]) {
+      throw Components.Exception('Do not allow multiple request on one interface: ' + aInterface);
+    }
+
+    let request = {interfaceName: aInterfaceName};
+    if (aCallback) {
+      let callback = aCallback.QueryInterface(Ci.nsICaptivePortalCallback);
+      request['callback'] = callback;
+      request['retryCount'] = 0;
+    }
+    this._addRequest(request);
+  },
+
+  abort: function abort(aInterfaceName) {
+    debug('abort for ' + aInterfaceName);
+    this._removeRequest(aInterfaceName);
+  },
+
+  finishPreparation: function finishPreparation(aInterfaceName) {
+    debug('finish preparation phase for interface "' + aInterfaceName + '"');
+    if (!this._runningRequest
+        || this._runningRequest.interfaceName !== aInterfaceName) {
+      debug('invalid finishPreparation for ' + aInterfaceName);
+      throw Components.Exception('only first request is allowed to invoke |finishPreparation|');
+      return;
+    }
+
+    this._startDetection();
+  },
+
+  cancelLogin: function cancelLogin(eventId) {
+    debug('login canceled by user for request "' + eventId + '"');
+    // Captive portal login procedure is canceled by user
+    if (this._runningRequest && this._runningRequest.hasOwnProperty('eventId')) {
+      let id = this._runningRequest.eventId;
+      if (eventId === id) {
+        this.executeCallback(false);
+      }
+    }
+  },
+
+  _applyDetection: function _applyDetection() {
+    debug('enter applyDetection('+ this._runningRequest.interfaceName + ')');
+
+    // Execute network interface preparation
+    if (this._runningRequest.hasOwnProperty('callback')) {
+      this._runningRequest.callback.prepare();
+    } else {
+      this._startDetection();
+    }
+  },
+
+  _startDetection: function _startDetection() {
+    debug('startDetection {site=' + this._canonicalSiteURL + ',content='
+          + this._canonicalSiteExpectedContent + ',time=' + this._maxWaitingTime + '}');
+    let self = this;
+
+    let urlFetcher = new URLFetcher(this._canonicalSiteURL, this._maxWaitingTime);
+
+    let requestDone = this.executeCallback.bind(this, true);
+    urlFetcher.ontimeout = requestDone;
+    urlFetcher.onerror = requestDone;
+    urlFetcher.onsuccess = function (content) {
+      if (self.validateContent(content)) {
+        requestDone();
+      } else {
+        // Content of the canonical website has been overwrite
+        self._startLogin();
+      }
+    };
+    urlFetcher.onredirectorerror = function (status) {
+      if (status >= 300 && status <= 399) {
+        // The canonical website has been redirected to an unknown location
+        self._startLogin();
+      } else if (self._runningRequest.retryCount++ < self._maxRetryCount) {
+        debug('startDetection-retry: ' + self._runningRequest.retryCount);
+        self._startDetection();
+      } else {
+        requestDone();
+      }
+    };
+
+    this._runningRequest['urlFetcher'] = urlFetcher;
+  },
+
+  _startLogin: function _startLogin() {
+    let id = this._allocateRequestId();
+    let details = {
+      type: kOpenCaptivePortalLoginEvent,
+      id: id,
+      url: this._canonicalSiteURL,
+    };
+    this._loginObserver.attach();
+    this._runningRequest['eventId'] = id;
+    this._sendEvent(kOpenCaptivePortalLoginEvent, details);
+  },
+
+  executeCallback: function executeCallback(success) {
+    if (this._runningRequest) {
+      debug('callback executed');
+      if (this._runningRequest.hasOwnProperty('callback')) {
+        this._runningRequest.callback.complete(success);
+      }
+
+      // Continue the following request
+      this._runningRequest['complete'] = true;
+      this._removeRequest(this._runningRequest.interfaceName);
+    }
+  },
+
+  _sendEvent: function _sendEvent(topic, details) {
+    debug('sendEvent "' + JSON.stringify(details) + '"');
+    Services.obs.notifyObservers(this,
+                                 topic,
+                                 JSON.stringify(details));
+  },
+
+  validateContent: function validateContent(content) {
+    debug('received content: ' + content);
+    return (content === this._canonicalSiteExpectedContent);
+  },
+
+  _allocateRequestId: function _allocateRequestId() {
+    let newId = this._nextRequestId++;
+    return newId.toString();
+  },
+
+  _runNextRequest: function _runNextRequest() {
+    let nextRequest = this._requestQueue.shift();
+    if (nextRequest) {
+      this._runningRequest = nextRequest;
+      this._applyDetection();
+    }
+  },
+
+  _addRequest: function _addRequest(request) {
+    this._interfaceNames[request.interfaceName] = true;
+    this._requestQueue.push(request);
+    if (!this._runningRequest) {
+      this._runNextRequest();
+    }
+  },
+
+  _removeRequest: function _removeRequest(aInterfaceName) {
+    if (!this._interfaceNames[aInterfaceName]) {
+      return;
+    }
+
+    delete this._interfaceNames[aInterfaceName];
+
+    if (this._runningRequest
+        && this._runningRequest.interfaceName === aInterfaceName) {
+      this._loginObserver.detach();
+
+      if (!this._runningRequest.complete) {
+        // Abort the user login procedure
+        if (this._runningRequest.hasOwnProperty('eventId')) {
+          let details = {
+            type: kAbortCaptivePortalLoginEvent,
+            id: this._runningRequest.eventId
+          };
+          this._sendEvent(kAbortCaptivePortalLoginEvent, details);
+        }
+
+        // Abort the ongoing HTTP request
+        if (this._runningRequest.hasOwnProperty('urlFetcher')) {
+          this._runningRequest.urlFetcher.abort();
+        }
+      }
+
+      debug('remove running request');
+      this._runningRequest = null;
+
+      // Continue next pending reqeust if the ongoing one has been aborted
+      this._runNextRequest();
+      return;
+    }
+
+    // Check if a pending request has been aborted
+    for (let i = 0; i < this._requestQueue.length; i++) {
+      if (this._requestQueue[i].interfaceName == aInterfaceName) {
+        this._requestQueue.splice(i, 1);
+
+        debug('remove pending request #' + i + ', remaining ' + this._requestQueue.length);
+        break;
+      }
+    }
+  },
+};
+
+let debug;
+if (DEBUG) {
+  debug = function (s) {
+    dump('-*- CaptivePortalDetector component: ' + s + '\n');
+  };
+} else {
+  debug = function (s) {};
+}
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([CaptivePortalDetector]);
new file mode 100644
--- /dev/null
+++ b/services/captivedetect/nsICaptivePortalDetector.idl
@@ -0,0 +1,53 @@
+/* -*- 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"
+
+[scriptable, uuid(593fdeec-6284-4de8-b416-8e63cbdc695e)]
+interface nsICaptivePortalCallback : nsISupports
+{
+  /**
+   * Preparation for network interface before captive portal detection started.
+   */
+  void prepare();
+
+  /**
+   * Invoke callbacks after captive portal detection finished.
+   */
+  void complete(in bool success);
+};
+
+[scriptable, uuid(2f827c5a-f551-477f-af09-71adbfbd854a)]
+interface nsICaptivePortalDetector : nsISupports
+{
+  /**
+   * Perform captive portal detection on specific network interface.
+   * @param ifname The name of network interface, exception will be thrwon
+   *               if the same interface has unfinished request.
+   * @param callback Callbacks when detection procedure starts and finishes.
+   */
+  void checkCaptivePortal(in wstring ifname,
+                          in nsICaptivePortalCallback callback);
+
+  /**
+   * Abort captive portal detection for specific network interface
+   * due to system failure, callback will not be invoked.
+   * @param ifname The name of network interface.
+   */
+  void abort(in wstring ifname);
+
+  /**
+   * Cancel captive portal login procedure by user, callback will be invoked.
+   * @param eventId Login event id provided in |captive-portal-login| event.
+   */
+  void cancelLogin(in wstring eventId);
+
+  /**
+   * Notify prepare phase is finished, routing and dns must be ready for sending
+   * out XMLHttpRequest. this is callback for CaptivePortalDetector API user.
+   * @param ifname The name of network interface, must be unique.
+   */
+  void finishPreparation(in wstring ifname);
+};
new file mode 100644
--- /dev/null
+++ b/services/captivedetect/services-captivedetect.js
@@ -0,0 +1,9 @@
+/* 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/. */
+
+pref("services.captivedetect.canonicalURL", "http://localhost/test.html");
+pref("services.captivedetect.canonicalContent", "true");
+pref("services.captivedetect.maxWaitingTime", 5000);
+pref("services.captivedetect.pollingTime", 3000);
+pref("services.captivedetect.maxRetryCount", 5);
--- a/services/makefiles.sh
+++ b/services/makefiles.sh
@@ -7,16 +7,17 @@ add_makefiles "
   services/common/Makefile
   services/crypto/Makefile
   services/crypto/component/Makefile
   services/healthreport/Makefile
   services/datareporting/Makefile
   services/metrics/Makefile
   services/sync/Makefile
   services/sync/locales/Makefile
+  services/captivedetect/Makefile
 "
 
 if [ "$ENABLE_TESTS" ]; then
   add_makefiles "
     services/common/tests/Makefile
     services/crypto/tests/Makefile
     services/healthreport/tests/Makefile
     services/datareporting/tests/Makefile
--- a/testing/mochitest/android.json
+++ b/testing/mochitest/android.json
@@ -121,16 +121,17 @@
  "content/xul/content/test/test_bug486990.xul": "TIMED_OUT",
  "docshell/test/navigation/test_bug13871.html": "RANDOM",
  "docshell/test/navigation/test_bug430723.html": "TIMED_OUT",
  "docshell/test/navigation/test_popup-navigates-children.html": "bug 783589",
  "docshell/test/navigation/test_sessionhistory.html": "RANDOM",
  "docshell/test/test_bug344861.html": "",
  "docshell/test/test_bug94514.html": "TIMED_OUT",
  "docshell/test/test_bug413310.html": "",
+ "docshell/test/test_bug590573.html": "bug 823022",
  "docshell/test/test_bug598895.html": "",
  "docshell/test/test_bug637644.html": "",
  "docshell/test/test_bug668513.html": "RANDOM",
  "docshell/test/test_framedhistoryframes.html": "bug 784321",
  "dom/browser-element/mochitest/test_browserElement_oop_SecurityChange.html": "TIMED_OUT, bug 766586",
  "dom/browser-element/mochitest/test_browserElement_inproc_AppFramePermission.html": "",
  "dom/browser-element/mochitest/test_browserElement_inproc_AppWindowNamespace.html": "TIMED_OUT, bug 783509",
  "dom/browser-element/mochitest/test_browserElement_inproc_SecurityChange.html": "TIMED_OUT, bug 766586",
--- a/toolkit/components/autocomplete/nsAutoCompleteController.cpp
+++ b/toolkit/components/autocomplete/nsAutoCompleteController.cpp
@@ -436,17 +436,17 @@ nsAutoCompleteController::HandleKeyNavig
         input->GetSelectionStart(&start);
         input->GetSelectionEnd(&end);
         if (start != end || end < (int32_t)text.Length())
           *_retval = false;
       }
 #endif
       if (*_retval) {
         // Open the popup if there has been a previous search, or else kick off a new search
-        if (mResults.Count() > 0) {
+        if (!mResults.IsEmpty()) {
           if (mRowCount) {
             OpenPopup();
           }
         } else {
           // Stop all searches in case they are async.
           StopSearch();
 
           if (!mInput) {
@@ -683,18 +683,17 @@ nsAutoCompleteController::OnUpdateSearch
   ClearResults();
   return OnSearchResult(aSearch, aResult);
 }
 
 NS_IMETHODIMP
 nsAutoCompleteController::OnSearchResult(nsIAutoCompleteSearch *aSearch, nsIAutoCompleteResult* aResult)
 {
   // look up the index of the search which is returning
-  uint32_t count = mSearches.Count();
-  for (uint32_t i = 0; i < count; ++i) {
+  for (uint32_t i = 0; i < mSearches.Length(); ++i) {
     if (mSearches[i] == aSearch) {
       ProcessResult(i, aResult);
     }
   }
 
   return NS_OK;
 }
 
@@ -998,33 +997,33 @@ nsAutoCompleteController::BeforeSearches
 
   // The first search result will clear mResults array, though we should pass
   // the previous result to each search to allow them to reuse it.  So we
   // temporarily cache current results till AfterSearches().
   if (!mResultCache.AppendObjects(mResults)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  mSearchesOngoing = mSearches.Count();
+  mSearchesOngoing = mSearches.Length();
   mSearchesFailed = 0;
   mFirstSearchResult = true;
 
   // notify the input that the search is beginning
   mInput->OnSearchBegin();
 
   return NS_OK;
 }
 
 nsresult
 nsAutoCompleteController::StartSearch(uint16_t aSearchType)
 {
   NS_ENSURE_STATE(mInput);
   nsCOMPtr<nsIAutoCompleteInput> input = mInput;
 
-  for (int32_t i = 0; i < mSearches.Count(); ++i) {
+  for (uint32_t i = 0; i < mSearches.Length(); ++i) {
     nsCOMPtr<nsIAutoCompleteSearch> search = mSearches[i];
 
     // Filter on search type.  Not all the searches implement this interface,
     // in such a case just consider them delayed.
     uint16_t searchType = nsIAutoCompleteSearchDescriptor::SEARCH_TYPE_DELAYED;
     nsCOMPtr<nsIAutoCompleteSearchDescriptor> searchDesc =
       do_QueryInterface(search);
     if (searchDesc)
@@ -1066,33 +1065,29 @@ nsAutoCompleteController::StartSearch(ui
 
   return NS_OK;
 }
 
 void
 nsAutoCompleteController::AfterSearches()
 {
   mResultCache.Clear();
-  // nsCOMArray::Count() returns a signed value; we have to cast it to unsigned
-  // when comparing it to unsigned, or compilers will complain.
-  if (mSearchesFailed == static_cast<uint32_t>(mSearches.Count()))
+  if (mSearchesFailed == mSearches.Length())
     PostSearchCleanup();
 }
 
 NS_IMETHODIMP
 nsAutoCompleteController::StopSearch()
 {
   // Stop the timer if there is one
   ClearSearchTimer();
 
   // Stop any ongoing asynchronous searches
   if (mSearchStatus == nsIAutoCompleteController::STATUS_SEARCHING) {
-    uint32_t count = mSearches.Count();
-
-    for (uint32_t i = 0; i < count; ++i) {
+    for (uint32_t i = 0; i < mSearches.Length(); ++i) {
       nsCOMPtr<nsIAutoCompleteSearch> search = mSearches[i];
       search->StopSearch();
     }
     mSearchesOngoing = 0;
     // since we were searching, but now we've stopped,
     // we need to call PostSearchCleanup()
     PostSearchCleanup();
   }
@@ -1110,28 +1105,26 @@ nsAutoCompleteController::StartSearches(
 
   // Get the timeout for delayed searches.
   uint32_t timeout;
   mInput->GetTimeout(&timeout);
 
   uint32_t immediateSearchesCount = mImmediateSearchesCount;
   if (timeout == 0) {
     // All the searches should be executed immediately.
-    immediateSearchesCount = mSearches.Count();
+    immediateSearchesCount = mSearches.Length();
   }
 
   if (immediateSearchesCount > 0) {
     nsresult rv = BeforeSearches();
     if (NS_FAILED(rv))
       return rv;
     StartSearch(nsIAutoCompleteSearchDescriptor::SEARCH_TYPE_IMMEDIATE);
 
-    // nsCOMArray::Count() returns a signed value; we have to cast it to
-    // unsigned when comparing it to unsigned, or compilers will complain.
-    if (static_cast<uint32_t>(mSearches.Count()) == immediateSearchesCount) {
+    if (mSearches.Length() == immediateSearchesCount) {
       // Either all searches are immediate, or the timeout is 0.  In the
       // latter case we still have to execute the delayed searches, otherwise
       // this will be a no-op.
       StartSearch(nsIAutoCompleteSearchDescriptor::SEARCH_TYPE_DELAYED);
 
       // All the searches have been started, just finish.
       AfterSearches();
       return NS_OK;
@@ -1202,18 +1195,17 @@ nsAutoCompleteController::EnterMatch(boo
       nsAutoString defaultIndexValue;
       if (NS_SUCCEEDED(GetFinalDefaultCompleteValue(defaultIndexValue)))
         value = defaultIndexValue;
     }
 
     if (forceComplete && value.IsEmpty()) {
       // Since nothing was selected, and forceComplete is specified, that means
       // we have to find the first default match and enter it instead
-      uint32_t count = mResults.Count();
-      for (uint32_t i = 0; i < count; ++i) {
+      for (uint32_t i = 0; i < mResults.Length(); ++i) {
         nsIAutoCompleteResult *result = mResults[i];
 
         if (result) {
           int32_t defaultIndex;
           result->GetDefaultIndex(&defaultIndex);
           if (defaultIndex >= 0) {
             result->GetValueAt(defaultIndex, value);
             break;
@@ -1680,22 +1672,21 @@ nsAutoCompleteController::GetResultValue
  * the search's results list.
  */
 nsresult
 nsAutoCompleteController::RowIndexToSearch(int32_t aRowIndex, int32_t *aSearchIndex, int32_t *aItemIndex)
 {
   *aSearchIndex = -1;
   *aItemIndex = -1;
 
-  uint32_t count = mSearches.Count();
   uint32_t index = 0;
 
   // Move index through the results of each registered nsIAutoCompleteSearch
   // until we find the given row
-  for (uint32_t i = 0; i < count; ++i) {
+  for (uint32_t i = 0; i < mSearches.Length(); ++i) {
     nsIAutoCompleteResult *result = mResults.SafeObjectAt(i);
     if (!result)
       continue;
 
     uint32_t rowCount = 0;
 
     // Skip past the result completely if it is marked as hidden
     bool isTypeAheadResult = false;
--- a/toolkit/components/places/nsNavHistoryResult.cpp
+++ b/toolkit/components/places/nsNavHistoryResult.cpp
@@ -227,30 +227,32 @@ nsNavHistoryResultNode::OnRemoving()
   mParent = nullptr;
 }
 
 
 /**
  * This will find the result for this node.  We can ask the nearest container
  * for this value (either ourselves or our parents should be a container,
  * and all containers have result pointers).
+ *
+ * @note The result may be null, if the container is detached from the result
+ *       who owns it.
  */
 nsNavHistoryResult*
 nsNavHistoryResultNode::GetResult()
 {
   nsNavHistoryResultNode* node = this;
   do {
     if (node->IsContainer()) {
       nsNavHistoryContainerResultNode* container = TO_CONTAINER(node);
-      NS_ASSERTION(container->mResult, "Containers must have valid results");
       return container->mResult;
     }
     node = node->mParent;
   } while (node);
-  NS_NOTREACHED("No container node found in hierarchy!");
+  MOZ_ASSERT(false, "No container node found in hierarchy!");
   return nullptr;
 }
 
 
 /**
  * Searches up the tree for the closest ancestor node that has an options
  * structure.  This will tell us the options that were used to generate this
  * node.
@@ -364,16 +366,17 @@ nsNavHistoryContainerResultNode::~nsNavH
  */
 void
 nsNavHistoryContainerResultNode::OnRemoving()
 {
   nsNavHistoryResultNode::OnRemoving();
   for (int32_t i = 0; i < mChildren.Count(); ++i)
     mChildren[i]->OnRemoving();
   mChildren.Clear();
+  mResult = nullptr;
 }
 
 
 bool
 nsNavHistoryContainerResultNode::AreChildrenVisible()
 {
   nsNavHistoryResult* result = GetResult();
   if (!result) {
@@ -686,35 +689,33 @@ nsNavHistoryContainerResultNode::Reverse
 uint16_t
 nsNavHistoryContainerResultNode::GetSortType()
 {
   if (mParent)
     return mParent->GetSortType();
   if (mResult)
     return mResult->mSortingMode;
 
-  NS_NOTREACHED("We should always have a result");
+  // This is a detached container, just use natural order.
   return nsINavHistoryQueryOptions::SORT_BY_NONE;
 }
 
 
 nsresult nsNavHistoryContainerResultNode::Refresh() {
   NS_WARNING("Refresh() is supported by queries or folders, not generic containers.");
   return NS_OK;
 }
 
 void
 nsNavHistoryContainerResultNode::GetSortingAnnotation(nsACString& aAnnotation)
 {
   if (mParent)
     mParent->GetSortingAnnotation(aAnnotation);
   else if (mResult)
     aAnnotation.Assign(mResult->mSortingAnnotation);
-  else
-    NS_NOTREACHED("We should always have a result");
 }
 
 /**
  * @return the sorting comparator function for the give sort type, or null if
  * there is no comparator.
  */
 nsNavHistoryContainerResultNode::SortComparator
 nsNavHistoryContainerResultNode::GetSortingComparator(uint16_t aSortType)
@@ -2046,16 +2047,17 @@ nsNavHistoryQueryResultNode::IsContainer
  * The base ResultNode::OnRemoving will clear some regular node stats, so it
  * is OK.
  */
 void
 nsNavHistoryQueryResultNode::OnRemoving()
 {
   nsNavHistoryResultNode::OnRemoving();
   ClearChildren(true);
+  mResult = nullptr;
 }
 
 
 /**
  * Marks the container as open, rebuilding results if they are invalid.  We
  * may still have valid results if the container was previously open and
  * nothing happened since closing it.
  *
@@ -2277,17 +2279,17 @@ nsNavHistoryQueryResultNode::FillChildre
   NS_ENSURE_SUCCESS(rv, rv);
 
   // it is important to call FillStats to fill in the parents on all
   // nodes and the result node pointers on the containers
   FillStats();
 
   uint16_t sortType = GetSortType();
 
-  if (mResult->mNeedsToApplySortingMode) {
+  if (mResult && mResult->mNeedsToApplySortingMode) {
     // We should repopulate container and then apply sortingMode.  To avoid
     // sorting 2 times we simply do that here.
     mResult->SetSortingMode(mResult->mSortingMode);
   }
   else if (mOptions->QueryType() != nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY ||
            sortType != nsINavHistoryQueryOptions::SORT_BY_NONE) {
     // The default SORT_BY_NONE sorts by the bookmark index (position), 
     // which we do not have for history queries.
@@ -2451,32 +2453,30 @@ nsNavHistoryQueryResultNode::Refresh()
 uint16_t
 nsNavHistoryQueryResultNode::GetSortType()
 {
   if (mParent)
     return mOptions->SortingMode();
   if (mResult)
     return mResult->mSortingMode;
 
-  NS_NOTREACHED("We should always have a result");
+  // This is a detached container, just use natural order.
   return nsINavHistoryQueryOptions::SORT_BY_NONE;
 }
 
 
 void
 nsNavHistoryQueryResultNode::GetSortingAnnotation(nsACString& aAnnotation) {
   if (mParent) {
     // use our sorting, we are not the root
     mOptions->GetSortingAnnotation(aAnnotation);
   }
   else if (mResult) {
     aAnnotation.Assign(mResult->mSortingAnnotation);
   }
-  else
-    NS_NOTREACHED("We should always have a result");
 }
 
 void
 nsNavHistoryQueryResultNode::RecursiveSort(
     const char* aData, SortComparator aComparator)
 {
   void* data = const_cast<void*>(static_cast<const void*>(aData));
 
@@ -3152,16 +3152,17 @@ nsNavHistoryFolderResultNode::~nsNavHist
  * The base ResultNode::OnRemoving will clear some regular node stats, so it is
  * OK.
  */
 void
 nsNavHistoryFolderResultNode::OnRemoving()
 {
   nsNavHistoryResultNode::OnRemoving();
   ClearChildren(true);
+  mResult = nullptr;
 }
 
 
 nsresult
 nsNavHistoryFolderResultNode::OpenContainer()
 {
   NS_ASSERTION(!mExpanded, "Container must be expanded to close it");
   nsresult rv;
@@ -3363,17 +3364,17 @@ nsNavHistoryFolderResultNode::FillChildr
  */
 nsresult
 nsNavHistoryFolderResultNode::OnChildrenFilled()
 {
   // It is important to call FillStats to fill in the parents on all
   // nodes and the result node pointers on the containers.
   FillStats();
 
-  if (mResult->mNeedsToApplySortingMode) {
+  if (mResult && mResult->mNeedsToApplySortingMode) {
     // We should repopulate container and then apply sortingMode.  To avoid
     // sorting 2 times we simply do that here.
     mResult->SetSortingMode(mResult->mSortingMode);
   }
   else {
     // Once we've computed all tree stats, we can sort, because containers will
     // then have proper visit counts and dates.
     SortComparator comparator = GetSortingComparator(GetSortType());
--- a/toolkit/components/viewsource/content/viewSource.js
+++ b/toolkit/components/viewsource/content/viewSource.js
@@ -541,17 +541,17 @@ function findLocation(pre, line, node, o
   // id attributes in the format <pre id="line123">, meaning that
   // the first line in the pre element is number 123.
   // However, in the plain text case, there is only one <pre> without an id,
   // so assume line 1.
   var curLine = pre.id ? parseInt(pre.id.substring(4)) : 1;
 
   // Walk through each of the text nodes and count newlines.
   var treewalker = window.content.document
-      .createTreeWalker(pre, NodeFilter.SHOW_TEXT, null, false);
+      .createTreeWalker(pre, NodeFilter.SHOW_TEXT, null);
 
   // The column number of the first character in the current text node.
   var firstCol = 1;
 
   var found = false;
   for (var textNode = treewalker.firstChild();
        textNode && !found;
        textNode = treewalker.nextNode()) {
--- a/toolkit/content/widgets/button.xml
+++ b/toolkit/content/widgets/button.xml
@@ -108,17 +108,17 @@
 
       <method name="fireAccessKeyButton">
         <parameter name="aSubtree"/>
         <parameter name="aAccessKeyLower"/>
         <body>
         <![CDATA[
           var iterator = aSubtree.ownerDocument.createTreeWalker(aSubtree, 
                                                                  NodeFilter.SHOW_ELEMENT, 
-                                                                 this.filterButtons, false);
+                                                                 this.filterButtons);
           while (iterator.nextNode()) {
             var test = iterator.currentNode;
             if (test.accessKey.toLowerCase() == aAccessKeyLower && 
                 !test.disabled && !test.collapsed && !test.hidden) {
               test.focus();
               test.click();
               return true;
             }
--- a/toolkit/content/widgets/radio.xml
+++ b/toolkit/content/widgets/radio.xml
@@ -255,18 +255,17 @@
           if (this.hasChildNodes()) {
             // Don't store the collected child nodes immediately,
             // collecting the child nodes could trigger constructors
             // which would blow away our list.
 
             const nsIDOMNodeFilter = Components.interfaces.nsIDOMNodeFilter;
             var iterator = doc.createTreeWalker(this,
                                                 nsIDOMNodeFilter.SHOW_ELEMENT,
-                                                this._filterRadioGroup,
-                                                true);
+                                                this._filterRadioGroup);
             while (iterator.nextNode())
               radioChildren.push(iterator.currentNode);
             return this._radioChildren = radioChildren;
           }
 
           // We don't have child nodes.
           const XUL_NS = "http://www.mozilla.org/keymaster/"
                        + "gatekeeper/there.is.only.xul";
--- a/toolkit/content/widgets/text.xml
+++ b/toolkit/content/widgets/text.xml
@@ -184,18 +184,17 @@
 
       <method name="wrapChar">
         <parameter name="element"/>
         <parameter name="index"/>
         <body>
           <![CDATA[
              var treeWalker = document.createTreeWalker(this,
                                                         NodeFilter.SHOW_TEXT,
-                                                        null,
-                                                        true);
+                                                        null);
              var node = treeWalker.nextNode();
              while (index >= node.length) {
                index -= node.length;
                node = treeWalker.nextNode();
              }
              if (index) {
                node = node.splitText(index);
              }