Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Tue, 22 Mar 2016 16:45:43 -0700
changeset 289897 3381aa98edf72e02b9d6b4db6efa0865063a2329
parent 289830 5453ae837f6a9394f01f2219c3998098f23a41fb (current diff)
parent 289896 42c21bf6657b9e67b265813ab44162d874e12d9d (diff)
child 289919 f9e8d838c9ee9b5f71984b82e6cf4f312fa108a4
child 289995 eb528d042c851c297f40543d63dfb8d1ed5361ce
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone48.0a1
Merge inbound to central, a=merge MozReview-Commit-ID: 8nLQgyb8Wfd
dom/base/test/chrome/test_bug574596.html
dom/base/test/chrome/test_bug599295.html
dom/base/test/test_bug357450.js
dom/xslt/nsIXSLTException.idl
js/xpconnect/tests/unit/test_bug641378.js
--- a/b2g/dev/moz.configure
+++ b/b2g/dev/moz.configure
@@ -1,7 +1,7 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-include('../common/moz.configure')
+include('../common.configure')
--- a/dom/asmjscache/AsmJSCache.cpp
+++ b/dom/asmjscache/AsmJSCache.cpp
@@ -7,16 +7,17 @@
 #include "AsmJSCache.h"
 
 #include <stdio.h>
 
 #include "js/RootingAPI.h"
 #include "jsfriendapi.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/CondVar.h"
+#include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/dom/asmjscache/PAsmJSCacheEntryChild.h"
 #include "mozilla/dom/asmjscache/PAsmJSCacheEntryParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/quota/Client.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/QuotaObject.h"
 #include "mozilla/dom/quota/UsageInfo.h"
@@ -29,17 +30,16 @@
 #include "nsIAtom.h"
 #include "nsIFile.h"
 #include "nsIIPCBackgroundChildCreateCallback.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "nsIRunnable.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIThread.h"
-#include "nsIXULAppInfo.h"
 #include "nsJSPrincipals.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
 #include "prio.h"
 #include "private/pprio.h"
 #include "mozilla/Services.h"
 
 #define ASMJSCACHE_METADATA_FILE_NAME "metadata"
@@ -1704,39 +1704,16 @@ CloseEntryForWrite(size_t aSize,
   // Flush to disk before writing the cookie (see OpenEntryForRead).
   if (PR_SyncMemMap(childRunnable->FileDesc(),
                     childRunnable->MappedMemory(),
                     childRunnable->FileSize()) == PR_SUCCESS) {
     *(AsmJSCookieType*)childRunnable->MappedMemory() = sAsmJSCookie;
   }
 }
 
-bool
-GetBuildId(JS::BuildIdCharVector* aBuildID)
-{
-  nsCOMPtr<nsIXULAppInfo> info = do_GetService("@mozilla.org/xre/app-info;1");
-  if (!info) {
-    return false;
-  }
-
-  nsCString buildID;
-  nsresult rv = info->GetPlatformBuildID(buildID);
-  NS_ENSURE_SUCCESS(rv, false);
-
-  if (!aBuildID->resize(buildID.Length())) {
-    return false;
-  }
-
-  for (size_t i = 0; i < buildID.Length(); i++) {
-    (*aBuildID)[i] = buildID[i];
-  }
-
-  return true;
-}
-
 class Client : public quota::Client
 {
   ~Client() {}
 
 public:
   NS_IMETHOD_(MozExternalRefCountType)
   AddRef() override;
 
--- a/dom/asmjscache/AsmJSCache.h
+++ b/dom/asmjscache/AsmJSCache.h
@@ -127,19 +127,16 @@ OpenEntryForWrite(nsIPrincipal* aPrincip
                   size_t aSize,
                   uint8_t** aMemory,
                   intptr_t* aHandle);
 void
 CloseEntryForWrite(size_t aSize,
                    uint8_t* aMemory,
                    intptr_t aHandle);
 
-bool
-GetBuildId(JS::BuildIdCharVector* aBuildId);
-
 // Called from QuotaManager.cpp:
 
 quota::Client*
 CreateClient();
 
 // Called from ipc/ContentParent.cpp:
 
 PAsmJSCacheEntryParent*
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2596,18 +2596,17 @@ nsJSContext::EnsureStatics()
 
   sPrevGCSliceCallback = JS::SetGCSliceCallback(sRuntime, DOMGCSliceCallback);
 
   // Set up the asm.js cache callbacks
   static const JS::AsmJSCacheOps asmJSCacheOps = {
     AsmJSCacheOpenEntryForRead,
     asmjscache::CloseEntryForRead,
     AsmJSCacheOpenEntryForWrite,
-    asmjscache::CloseEntryForWrite,
-    asmjscache::GetBuildId
+    asmjscache::CloseEntryForWrite
   };
   JS::SetAsmJSCacheOps(sRuntime, &asmJSCacheOps);
 
   // Set these global xpconnect options...
   Preferences::RegisterCallbackAndCall(ReportAllJSExceptionsPrefChangedCallback,
                                        "dom.report_all_js_exceptions");
 
   Preferences::RegisterCallbackAndCall(SetMemoryHighWaterMarkPrefChangedCallback,
--- a/dom/base/test/chrome.ini
+++ b/dom/base/test/chrome.ini
@@ -12,17 +12,16 @@ support-files =
 [test_bug715041_removal.xul]
 [test_domrequesthelper.xul]
 [test_url.xul]
 [test_console.xul]
 [test_navigator_resolve_identity_xrays.xul]
 support-files = file_navigator_resolve_identity_xrays.xul
 [test_sendQueryContentAndSelectionSetEvent.html]
 [test_bug1016960.html]
-[test_bug357450.js]
 [test_copypaste.xul]
 [test_messagemanager_principal.html]
 [test_messagemanager_send_principal.html]
 skip-if = buildapp == 'mulet'
 [test_bug945152.html]
 run-if = os == 'linux'
 [test_bug1008126.html]
 run-if = os == 'linux'
--- a/dom/base/test/chrome/chrome.ini
+++ b/dom/base/test/chrome/chrome.ini
@@ -25,31 +25,30 @@ support-files =
   host_bug814638.xul
   window_nsITextInputProcessor.xul
   title_window.xul
 
 [test_bug120684.xul]
 [test_bug206691.xul]
 [test_bug339494.xul]
 [test_bug357450.xul]
+support-files = ../file_bug357450.js
 [test_bug380418.html]
 [test_bug380418.html^headers^]
 [test_bug383430.html]
 [test_bug391728.html]
 [test_bug418986-1.xul]
 [test_bug421622.xul]
 [test_bug429785.xul]
 [test_bug430050.xul]
 [test_bug467123.xul]
 [test_bug549682.xul]
 [test_bug571390.xul]
-[test_bug574596.html]
 [test_bug1098074_throw_from_ReceiveMessage.xul]
 skip-if = buildapp == 'mulet'
-[test_bug599295.html]
 [test_bug616841.xul]
 [test_bug635835.xul]
 [test_bug650776.html]
 [test_bug650784.html]
 [test_bug682305.html]
 [test_bug683852.xul]
 [test_bug750096.html]
 [test_bug752226-3.xul]
--- a/dom/base/test/chrome/test_bug357450.xul
+++ b/dom/base/test/chrome/test_bug357450.xul
@@ -7,17 +7,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 -->
 
 <window title="Mozilla Bug 357450"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <script type="application/javascript" 
 	  src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>      
   <!-- This file is shared with non-chrome tests -->
-  <script type="text/javascript" src="../test_bug357450.js"></script>
+  <script type="text/javascript" src="file_bug357450.js"></script>
 
 <body  xmlns="http://www.w3.org/1999/xhtml">
 
 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=357450"
    target="_blank">Mozilla Bug 357450</a>
 
 <p id="display"></p>
 
deleted file mode 100644
--- a/dom/base/test/chrome/test_bug574596.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=574596
--->
-<head>
-  <title>Test for Bug 574596</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript"  src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-  <script type="application/javascript"  src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=574596">Mozilla Bug 574596</a>
-<style type="text/css">
-#link1 a { -moz-user-select:none; }
-</style>
-<div id="link1"><a href="http://www.mozilla.org/">link1</a></div>
-<div id="link2"><a href="http://www.mozilla.org/">link2</a></div>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 574596 **/
-
-function ignoreFunc(actualData, expectedData) {
-  return true;
-}
-
-var dragLinkText = [[
-  { type:"text/x-moz-url",          data:"", eqTest:ignoreFunc },
-  { type:"text/x-moz-url-data",     data:"http://www.mozilla.org/" },
-  { type:"text/x-moz-url-desc",     data:"link1" },
-  { type:"text/uri-list",           data:"http://www.mozilla.org/" },
-  { type:"text/_moz_htmlcontext",   data:"", eqTest:ignoreFunc },
-  { type:"text/_moz_htmlinfo",      data:"", eqTest:ignoreFunc },
-  { type:"text/html",               data:'<div id="link1"><a href="http://www.mozilla.org/">link1</a></div>' },
-  { type:"text/plain",              data:"http://www.mozilla.org/" }
-]];
-
-
-function dumpTransfer(dataTransfer,expect) {
-  dtData = dataTransfer.mozItemCount + "items:\n";
-  for (var i = 0; i < dataTransfer.mozItemCount; i++) {
-    var dtTypes = dataTransfer.mozTypesAt(i);
-    for (var j = 0; j < dtTypes.length; j++) {
-      var actualData = dataTransfer.mozGetDataAt(dtTypes[j],i)
-      if (expect && expect[i] && expect[i][j]) {
-        if (expect[i][j].eqTest)
-          dtData += expect[i][j].eqTest(actualData,expect[i][j].data) ? "ok" : "fail";
-        else
-          dtData += (actualData == expect[i][j].data) ? "ok" : "fail";
-      }
-      dtData += "["+i+"]" + "["+j+"]: " + '"' + dtTypes[j] + '"  "' + actualData + '"\n';
-    }
-  }
-  alert(dtData);
-}
-
-function runTest() {
-  var result = synthesizeDragStart($('link1'), dragLinkText, window);
-  is(result, null, "Drag -moz-user-select:none link (#link1)");
-  // if (result) dumpTransfer(result,dragLinkText);
-
-  dragLinkText[0][2].data = "link2";
-  dragLinkText[0][6].data = '<div id="link2"><a href="http://www.mozilla.org/">link2</a></div>'
-  var result = synthesizeDragStart($('link2'), dragLinkText, window);
-  is(result, null, "Drag link (#link2)");
-  // if (result) dumpTransfer(result,dragLinkText);
-
-  SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTest);
-
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/dom/base/test/chrome/test_bug599295.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=599295
--->
-<head>
-  <title>Test for Bug 599295</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript"  src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
-  <script type="application/javascript"  src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=599295">Mozilla Bug 599295</a>
-<style type="text/css">
-#link1 a { -moz-user-select:none; }
-</style>
-<div id="link1"><a href="http://www.mozilla.org/">link1</a></div>
-<div id="link2"><a href="http://www.mozilla.org/">link2</a></div>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 599295 **/
-
-/* Do not allow a response to a CONNECT method, used to establish an
-   SSL tunnel over an HTTP proxy, to contain a redirect */
-
-const BinaryInputStream = 
-    Components.Constructor("@mozilla.org/binaryinputstream;1",
-                           "nsIBinaryInputStream",
-                           "setInputStream");
-
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-Cu.import("resource://gre/modules/NetUtil.jsm");
-
-var listener = {
- _httpstatus : 0,
-
- onStartRequest: function(request, context) {
-   request.QueryInterface(Components.interfaces.nsIHttpChannel);
-   _httpstatus = request.responseStatus;
- },
-
- onDataAvailable: function(request, context, stream, offset, count) {
-   new BinaryInputStream(stream).readByteArray(count);
- },
-
- onStopRequest: function(request, context, status) {
-  /* testing here that the redirect was not followed. If it was followed
-     we would see a http status of 200 and status of NS_OK */
-
-   is(_httpstatus, 302, "http status 302");
-   is(status, Components.results.NS_ERROR_CONNECTION_REFUSED, "raised refused");
-   SimpleTest.finish();
-  }
-};
-
-function runTest() {
-  var uri = NetUtil.newURI("https://redirproxy.example.com/test");
-  var channel = NetUtil.newChannel({uri: uri, loadUsingSystemPrincipal: true});
-
-  /* Previously, necko would allow a 302 as part of a CONNECT response
-     if the LOAD_DOCUMENT_URI flag was set and the original document
-     URI had not yet been changed. */
- 
-  channel.loadFlags |= Components.interfaces.nsIChannel.LOAD_DOCUMENT_URI;
-  channel.QueryInterface(Components.interfaces.nsIHttpChannelInternal);
-  channel.documentURI = uri;
-  channel.asyncOpen2(listener);
-}
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(runTest);
-
-</script>
-</pre>
-</body>
-</html>
-
rename from dom/base/test/test_bug357450.js
rename to dom/base/test/file_bug357450.js
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -446,17 +446,17 @@ skip-if = buildapp == 'b2g' || toolkit =
 [test_bug343596.html]
 [test_bug345339.html]
 [test_bug346485.html]
 [test_bug352728.html]
 [test_bug352728.xhtml]
 [test_bug353334.html]
 [test_bug355026.html]
 [test_bug357450.html]
-support-files = test_bug357450.js
+support-files = file_bug357450.js
 [test_bug357450.xhtml]
 [test_bug357450_svg.xhtml]
 [test_bug357509.html]
 [test_bug358660.html]
 [test_bug362391.xhtml]
 [test_bug364092.xhtml]
 [test_bug364413.xhtml]
 [test_bug366944.html]
@@ -602,28 +602,31 @@ skip-if = (buildapp == 'b2g' && toolkit 
 skip-if = (os == "android") # Failure with AccessibleCarets on Android, bug 1230229
 [test_bug562137.html]
 [test_bug562169-1.html]
 [test_bug562169-2.html]
 [test_bug562652.html]
 [test_bug564047.html]
 [test_bug564863.xhtml]
 [test_bug567350.html]
+[test_bug574596.html]
+skip-if = toolkit == 'android'
 [test_bug578096.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(debug-only failure; crash) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_bug585978.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only timeout
 [test_bug587931.html]
 [test_bug588990.html]
 [test_bug590812.html]
 skip-if = toolkit == 'android' #bug 687032
 [test_bug590870.html]
 [test_bug592366.html]
 [test_bug592829.html]
 [test_bug597345.html]
+[test_bug599295.html]
 [test_bug599588.html]
 [test_bug601803.html]
 [test_bug602838.html]
 [test_bug604592.html]
 [test_bug604660.html]
 [test_bug605982.html]
 [test_bug606729.html]
 [test_bug614058.html]
--- a/dom/base/test/test_bug357450.html
+++ b/dom/base/test/test_bug357450.html
@@ -2,17 +2,17 @@
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=357450
 -->
 
 <head>
   <title>Test for Bug 357450</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="test_bug357450.js"></script>     
+  <script type="text/javascript" src="file_bug357450.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <style type="text/css">
 
   </style>
 </head>
 
 <body>
 
--- a/dom/base/test/test_bug357450.xhtml
+++ b/dom/base/test/test_bug357450.xhtml
@@ -1,19 +1,19 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=357450
 -->
 
 <head>
   <title>Test for Bug 357450</title>
-  <script type="text/javascript" 
-	  src="/tests/SimpleTest/SimpleTest.js"></script>       
-  <script type="text/javascript" src="test_bug357450.js"></script>      
+  <script type="text/javascript"
+          src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="file_bug357450.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 
 <body>
 
 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=357450"
    target="_blank">Mozilla Bug 357450</a>
 
--- a/dom/base/test/test_bug357450_svg.xhtml
+++ b/dom/base/test/test_bug357450_svg.xhtml
@@ -2,18 +2,18 @@
 
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=357450
 -->
 
 <head>
   <title>Test for Bug 357450</title>
   <script type="text/javascript"
-          src="/tests/SimpleTest/SimpleTest.js"></script>       
-  <script type="text/javascript" src="test_bug357450.js"></script>      
+          src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="file_bug357450.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
 </head>
 
 <body>
 
 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=357450"
    target="_blank">Mozilla Bug 357450</a>
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_bug574596.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=574596
+-->
+<head>
+  <title>Test for Bug 574596</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"  src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=574596">Mozilla Bug 574596</a>
+<style type="text/css">
+#link1 a { -moz-user-select:none; }
+</style>
+<div id="link1"><a href="http://www.mozilla.org/">link1</a></div>
+<div id="link2"><a href="http://www.mozilla.org/">link2</a></div>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 574596 **/
+
+function ignoreFunc(actualData, expectedData) {
+  return true;
+}
+
+var dragLinkText = [[
+  { type:"text/x-moz-url",          data:"", eqTest:ignoreFunc },
+  { type:"text/x-moz-url-data",     data:"http://www.mozilla.org/" },
+  { type:"text/x-moz-url-desc",     data:"link1" },
+  { type:"text/uri-list",           data:"http://www.mozilla.org/" },
+  { type:"text/_moz_htmlcontext",   data:"", eqTest:ignoreFunc },
+  { type:"text/_moz_htmlinfo",      data:"", eqTest:ignoreFunc },
+  { type:"text/html",               data:'<div id="link1"><a href="http://www.mozilla.org/">link1</a></div>' },
+  { type:"text/plain",              data:"http://www.mozilla.org/" }
+]];
+
+
+function dumpTransfer(dataTransfer,expect) {
+  dtData = dataTransfer.mozItemCount + "items:\n";
+  for (var i = 0; i < dataTransfer.mozItemCount; i++) {
+    var dtTypes = dataTransfer.mozTypesAt(i);
+    for (var j = 0; j < dtTypes.length; j++) {
+      var actualData = dataTransfer.mozGetDataAt(dtTypes[j],i)
+      if (expect && expect[i] && expect[i][j]) {
+        if (expect[i][j].eqTest)
+          dtData += expect[i][j].eqTest(actualData,expect[i][j].data) ? "ok" : "fail";
+        else
+          dtData += (actualData == expect[i][j].data) ? "ok" : "fail";
+      }
+      dtData += "["+i+"]" + "["+j+"]: " + '"' + dtTypes[j] + '"  "' + actualData + '"\n';
+    }
+  }
+  alert(dtData);
+}
+
+function runTest() {
+  var result = synthesizeDragStart($('link1'), dragLinkText, window);
+  is(result, null, "Drag -moz-user-select:none link (#link1)");
+  // if (result) dumpTransfer(result,dragLinkText);
+
+  dragLinkText[0][2].data = "link2";
+  dragLinkText[0][6].data = '<div id="link2"><a href="http://www.mozilla.org/">link2</a></div>'
+  var result = synthesizeDragStart($('link2'), dragLinkText, window);
+  is(result, null, "Drag link (#link2)");
+  // if (result) dumpTransfer(result,dragLinkText);
+
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTest);
+
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_bug599295.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=599295
+-->
+<head>
+  <title>Test for Bug 599295</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"  src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=599295">Mozilla Bug 599295</a>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 599295 **/
+
+/* Do not allow a response to a CONNECT method, used to establish an
+   SSL tunnel over an HTTP proxy, to contain a redirect */
+
+function runTest() {
+  /* Previously, necko would allow a 302 as part of a CONNECT response
+     if the LOAD_DOCUMENT_URI flag was set and the original document
+     URI had not yet been changed. */
+
+  SpecialPowers.loadChannelAndReturnStatus("https://redirproxy.example.com/test",
+                                           true)
+    .then(function({status, httpStatus}) {
+      /* testing here that the redirect was not followed. If it was followed
+         we would see a http status of 200 and status of NS_OK */
+
+      is(httpStatus, 302, "http status 302");
+      is(status, SpecialPowers.Cr.NS_ERROR_CONNECTION_REFUSED,
+         "raised refused");
+      SimpleTest.finish();
+    });
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTest);
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/dom/bluetooth/bluedroid/BluetoothDaemonA2dpInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonA2dpInterface.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "BluetoothDaemonA2dpInterface.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/unused.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 using namespace mozilla::ipc;
 
 //
 // A2DP module
@@ -49,49 +50,51 @@ BluetoothDaemonA2dpModule::HandleSvc(con
 //
 
 nsresult
 BluetoothDaemonA2dpModule::ConnectCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothA2dpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(new DaemonSocketPDU(SERVICE_ID,
-                                                     OPCODE_CONNECT,
-                                                     6)); // Address
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CONNECT,
+                                6); // Address
+
   nsresult rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonA2dpModule::DisconnectCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothA2dpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(new DaemonSocketPDU(SERVICE_ID,
-                                                     OPCODE_DISCONNECT,
-                                                     6)); // Address
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_DISCONNECT,
+                                6); // Address
+
   nsresult rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 // Responses
 //
 
 void
 BluetoothDaemonA2dpModule::ErrorRsp(
--- a/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "BluetoothDaemonAvrcpInterface.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/unused.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 using namespace mozilla::ipc;
 
 //
 // AVRCP module
@@ -49,251 +50,255 @@ BluetoothDaemonAvrcpModule::HandleSvc(co
 
 nsresult
 BluetoothDaemonAvrcpModule::GetPlayStatusRspCmd(
   ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos,
   BluetoothAvrcpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_PLAY_STATUS_RSP,
-                           1 + // Play status
-                           4 + // Duration
-                           4)); // Position
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_PLAY_STATUS_RSP,
+                                1 + // Play status
+                                4 + // Duration
+                                4); // Position
 
   nsresult rv = PackPDU(aPlayStatus, aSongLen, aSongPos, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonAvrcpModule::ListPlayerAppAttrRspCmd(
   int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs,
   BluetoothAvrcpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_LIST_PLAYER_APP_ATTR_RSP,
-                           1 + // # Attributes
-                           aNumAttr)); // Player attributes
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_LIST_PLAYER_APP_ATTR_RSP,
+                                1 + // # Attributes
+                                aNumAttr); // Player attributes
 
   nsresult rv = PackPDU(
     PackConversion<int, uint8_t>(aNumAttr),
     PackArray<BluetoothAvrcpPlayerAttribute>(aPAttrs, aNumAttr), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonAvrcpModule::ListPlayerAppValueRspCmd(
   int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_LIST_PLAYER_APP_VALUE_RSP,
-                           1 + // # Values
-                           aNumVal)); // Player values
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_LIST_PLAYER_APP_VALUE_RSP,
+                                1 + // # Values
+                                aNumVal); // Player values
 
   nsresult rv = PackPDU(PackConversion<int, uint8_t>(aNumVal),
                         PackArray<uint8_t>(aPVals, aNumVal), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonAvrcpModule::GetPlayerAppValueRspCmd(
   uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues,
   BluetoothAvrcpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_RSP,
-                           1 + // # Pairs
-                           2 * aNumAttrs)); // Attribute-value pairs
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_RSP,
+                                1 + // # Pairs
+                                2 * aNumAttrs); // Attribute-value pairs
+
   nsresult rv = PackPDU(
     aNumAttrs,
     BluetoothAvrcpAttributeValuePairs(aIds, aValues, aNumAttrs), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonAvrcpModule::GetPlayerAppAttrTextRspCmd(
   int aNumAttr, const uint8_t* aIds, const char** aTexts,
   BluetoothAvrcpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_ATTR_TEXT_RSP,
-                           0)); // Dynamically allocated
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_PLAYER_APP_ATTR_TEXT_RSP,
+                                0); // Dynamically allocated
+
   nsresult rv = PackPDU(
     PackConversion<int, uint8_t>(aNumAttr),
     BluetoothAvrcpAttributeTextPairs(aIds, aTexts, aNumAttr), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonAvrcpModule::GetPlayerAppValueTextRspCmd(
   int aNumVal, const uint8_t* aIds, const char** aTexts,
   BluetoothAvrcpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_TEXT_RSP,
-                           0)); // Dynamically allocated
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_TEXT_RSP,
+                                0); // Dynamically allocated
+
   nsresult rv = PackPDU(
     PackConversion<int, uint8_t>(aNumVal),
     BluetoothAvrcpAttributeTextPairs(aIds, aTexts, aNumVal), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonAvrcpModule::GetElementAttrRspCmd(
   uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttr,
   BluetoothAvrcpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_ELEMENT_ATTR_RSP,
-                           0)); // Dynamically allocated
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_ELEMENT_ATTR_RSP,
+                                0); // Dynamically allocated
+
   nsresult rv = PackPDU(
     aNumAttr,
     PackArray<BluetoothAvrcpElementAttribute>(aAttr, aNumAttr), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonAvrcpModule::SetPlayerAppValueRspCmd(
   BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_PLAYER_APP_VALUE_RSP,
-                           1)); // Status code
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SET_PLAYER_APP_VALUE_RSP,
+                                1); // Status code
 
   nsresult rv = PackPDU(aRspStatus, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonAvrcpModule::RegisterNotificationRspCmd(
   BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType,
   const BluetoothAvrcpNotificationParam& aParam,
   BluetoothAvrcpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_REGISTER_NOTIFICATION_RSP,
-                           1 + // Event
-                           1 + // Type
-                           1 + // Data length
-                           256)); // Maximum data length
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_REGISTER_NOTIFICATION_RSP,
+                                1 + // Event
+                                1 + // Type
+                                1 + // Data length
+                                256); // Maximum data length
 
   BluetoothAvrcpEventParamPair data(aEvent, aParam);
   nsresult rv = PackPDU(aEvent, aType, static_cast<uint8_t>(data.GetLength()),
                         data, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonAvrcpModule::SetVolumeCmd(uint8_t aVolume,
                                          BluetoothAvrcpResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_VOLUME,
-                           1)); // Volume
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SET_VOLUME,
+                                1); // Volume
 
   nsresult rv = PackPDU(aVolume, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 // Responses
 //
 
 void
 BluetoothDaemonAvrcpModule::ErrorRsp(
--- a/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "BluetoothDaemonCoreInterface.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/unused.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 using namespace mozilla::ipc;
 
 //
 // Core module
@@ -47,441 +48,442 @@ BluetoothDaemonCoreModule::HandleSvc(con
 // Commands
 //
 
 nsresult
 BluetoothDaemonCoreModule::EnableCmd(BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_ENABLE,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_ENABLE,
+                                0);
 
-  nsresult rv = Send(pdu, aRes);
+  nsresult rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::DisableCmd(BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_DISABLE,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_DISABLE,
+                                0);
 
-  nsresult rv = Send(pdu, aRes);
+  nsresult rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::GetAdapterPropertiesCmd(
   BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_ADAPTER_PROPERTIES,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_ADAPTER_PROPERTIES,
+                                0);
 
-  nsresult rv = Send(pdu, aRes);
+  nsresult rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::GetAdapterPropertyCmd(
   BluetoothPropertyType aType, BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_ADAPTER_PROPERTY,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_ADAPTER_PROPERTY,
+                                0);
 
   nsresult rv = PackPDU(aType, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::SetAdapterPropertyCmd(
   const BluetoothProperty& aProperty, BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_ADAPTER_PROPERTY,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SET_ADAPTER_PROPERTY,
+                                0);
 
   nsresult rv = PackPDU(aProperty, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::GetRemoteDevicePropertiesCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_REMOTE_DEVICE_PROPERTIES,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_REMOTE_DEVICE_PROPERTIES,
+                                0);
 
   nsresult rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::GetRemoteDevicePropertyCmd(
   const BluetoothAddress& aRemoteAddr,
   BluetoothPropertyType aType,
   BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_REMOTE_DEVICE_PROPERTY,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_REMOTE_DEVICE_PROPERTY,
+                                0);
 
   nsresult rv = PackPDU(aRemoteAddr, aType, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::SetRemoteDevicePropertyCmd(
   const BluetoothAddress& aRemoteAddr,
   const BluetoothProperty& aProperty,
   BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_REMOTE_DEVICE_PROPERTY,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SET_REMOTE_DEVICE_PROPERTY,
+                                0);
 
   nsresult rv = PackPDU(aRemoteAddr, aProperty, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::GetRemoteServiceRecordCmd(
   const BluetoothAddress& aRemoteAddr, const BluetoothUuid& aUuid,
   BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_REMOTE_SERVICE_RECORD,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_REMOTE_SERVICE_RECORD,
+                                0);
 
   nsresult rv = PackPDU(aRemoteAddr, aUuid, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::GetRemoteServicesCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_REMOTE_SERVICES, 0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_REMOTE_SERVICES,
+                                0);
 
   nsresult rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::StartDiscoveryCmd(BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_START_DISCOVERY,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_START_DISCOVERY,
+                                0);
 
-  nsresult rv = Send(pdu, aRes);
+  nsresult rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::CancelDiscoveryCmd(BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CANCEL_DISCOVERY,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CANCEL_DISCOVERY,
+                                0);
 
-  nsresult rv = Send(pdu, aRes);
+  nsresult rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::CreateBondCmd(const BluetoothAddress& aBdAddr,
                                          BluetoothTransport aTransport,
                                          BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CREATE_BOND,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CREATE_BOND,
+                                0);
 
 #if ANDROID_VERSION >= 21
   nsresult rv = PackPDU(aBdAddr, aTransport, *pdu);
 #else
   nsresult rv = PackPDU(aBdAddr, *pdu);
 #endif
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::RemoveBondCmd(const BluetoothAddress& aBdAddr,
                                          BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_REMOVE_BOND,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_REMOVE_BOND,
+                                0);
 
   nsresult rv = PackPDU(aBdAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::CancelBondCmd(const BluetoothAddress& aBdAddr,
                                          BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CANCEL_BOND,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CANCEL_BOND,
+                                0);
 
   nsresult rv = PackPDU(aBdAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::PinReplyCmd(const BluetoothAddress& aBdAddr,
                                        bool aAccept,
                                        const BluetoothPinCode& aPinCode,
                                        BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_PIN_REPLY,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_PIN_REPLY,
+                                0);
 
   nsresult rv = PackPDU(aBdAddr, aAccept, aPinCode, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::SspReplyCmd(const BluetoothAddress& aBdAddr,
                                        BluetoothSspVariant aVariant,
                                        bool aAccept, uint32_t aPasskey,
                                        BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SSP_REPLY,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SSP_REPLY,
+                                0);
 
   nsresult rv = PackPDU(aBdAddr, aVariant, aAccept, aPasskey, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::DutModeConfigureCmd(
   bool aEnable, BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_DUT_MODE_CONFIGURE,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_DUT_MODE_CONFIGURE,
+                                0);
 
   nsresult rv = PackPDU(aEnable, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::DutModeSendCmd(uint16_t aOpcode,
                                           uint8_t* aBuf, uint8_t aLen,
                                           BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_DUT_MODE_SEND,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_DUT_MODE_SEND,
+                                0);
 
   nsresult rv = PackPDU(aOpcode, aLen, PackArray<uint8_t>(aBuf, aLen),
                         *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonCoreModule::LeTestModeCmd(uint16_t aOpcode,
                                          uint8_t* aBuf, uint8_t aLen,
                                          BluetoothCoreResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_LE_TEST_MODE,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_LE_TEST_MODE,
+                                0);
 
   nsresult rv = PackPDU(aOpcode, aLen, PackArray<uint8_t>(aBuf, aLen),
                         *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 // Responses
 //
 
 void
 BluetoothDaemonCoreModule::ErrorRsp(const DaemonSocketPDUHeader& aHeader,
--- a/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "BluetoothDaemonGattInterface.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/unused.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 using namespace mozilla::ipc;
 
 //
 // GATT module
@@ -49,559 +50,562 @@ BluetoothDaemonGattModule::HandleSvc(con
 //
 
 nsresult
 BluetoothDaemonGattModule::ClientRegisterCmd(
   const BluetoothUuid& aUuid, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_REGISTER,
-                        16)); // Service UUID
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_REGISTER,
+                                16); // Service UUID
 
   nsresult rv = PackPDU(aUuid, *pdu);
 
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientUnregisterCmd(
   int aClientIf, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_UNREGISTER,
-                        4)); // Client Interface
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_UNREGISTER,
+                                4); // Client Interface
 
   nsresult rv = PackPDU(aClientIf, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientScanCmd(
   int aClientIf, bool aStart, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_SCAN,
-                        4 + // Client Interface
-                        1)); // Start
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_SCAN,
+                                4 + // Client Interface
+                                1); // Start
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aClientIf),
                         PackConversion<bool, uint8_t>(aStart), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientConnectCmd(
   int aClientIf, const BluetoothAddress& aBdAddr, bool aIsDirect,
   BluetoothTransport aTransport, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_CONNECT,
-                        4 + // Client Interface
-                        6 + // Remote Address
-                        1 + // Is Direct
-                        4)); // Transport
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_CONNECT,
+                                4 + // Client Interface
+                                6 + // Remote Address
+                                1 + // Is Direct
+                                4); // Transport
 
   nsresult rv = PackPDU(
     PackConversion<int, int32_t>(aClientIf),
     aBdAddr,
     PackConversion<bool, uint8_t>(aIsDirect),
     PackConversion<BluetoothTransport, int32_t>(aTransport), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientDisconnectCmd(
   int aClientIf, const BluetoothAddress& aBdAddr, int aConnId,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_DISCONNECT,
-                        4 + // Client Interface
-                        6 + // Remote Address
-                        4)); // Connection ID
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_DISCONNECT,
+                                4 + // Client Interface
+                                6 + // Remote Address
+                                4); // Connection ID
 
   nsresult rv;
   rv = PackPDU(PackConversion<int, int32_t>(aClientIf),
                aBdAddr,
                PackConversion<int, int32_t>(aConnId), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientListenCmd(
   int aClientIf, bool aIsStart, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_LISTEN,
-                        4 + // Client Interface
-                        1)); // Start
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_LISTEN,
+                                4 + // Client Interface
+                                1); // Start
 
   nsresult rv;
   rv = PackPDU(PackConversion<int, int32_t>(aClientIf),
                PackConversion<bool, uint8_t>(aIsStart), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientRefreshCmd(
   int aClientIf, const BluetoothAddress& aBdAddr,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_REFRESH,
-                        4 + // Client Interface
-                        6)); // Remote Address
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_REFRESH,
+                                4 + // Client Interface
+                                6); // Remote Address
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aClientIf),
                         aBdAddr,
                         *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientSearchServiceCmd(
   int aConnId, bool aFiltered, const BluetoothUuid& aUuid,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_SEARCH_SERVICE,
-                        4 + // Connection ID
-                        1 + // Filtered
-                        16)); // UUID
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_SEARCH_SERVICE,
+                                4 + // Connection ID
+                                1 + // Filtered
+                                16); // UUID
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aConnId),
                         PackConversion<bool, uint8_t>(aFiltered),
                         PackReversed<BluetoothUuid>(aUuid),
                         *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientGetIncludedServiceCmd(
   int aConnId, const BluetoothGattServiceId& aServiceId, bool aContinuation,
   const BluetoothGattServiceId& aStartServiceId,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_GET_INCLUDED_SERVICE,
-                        4 + // Connection ID
-                        18 + // Service ID
-                        1 + // Continuation
-                        18)); // Start Service ID
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_GET_INCLUDED_SERVICE,
+                                4 + // Connection ID
+                                18 + // Service ID
+                                1 + // Continuation
+                                18); // Start Service ID
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aConnId), aServiceId,
                         PackConversion<bool, uint8_t>(aContinuation),
                         aStartServiceId, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientGetCharacteristicCmd(
   int aConnId, const BluetoothGattServiceId& aServiceId, bool aContinuation,
   const BluetoothGattId& aStartCharId,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_GET_CHARACTERISTIC,
-                        4 + // Connection ID
-                        18 + // Service ID
-                        1 + // Continuation
-                        17)); // Start Characteristic ID
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_GET_CHARACTERISTIC,
+                                4 + // Connection ID
+                                18 + // Service ID
+                                1 + // Continuation
+                                17); // Start Characteristic ID
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aConnId), aServiceId,
                         PackConversion<bool, uint8_t>(aContinuation),
                         aStartCharId, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientGetDescriptorCmd(
   int aConnId, const BluetoothGattServiceId& aServiceId,
   const BluetoothGattId& aCharId, bool aContinuation,
   const BluetoothGattId& aStartDescriptorId,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_GET_DESCRIPTOR,
-                        4 + // Connection ID
-                        18 + // Service ID
-                        17 + // Characteristic ID
-                        1 + // Continuation
-                        17)); // Start Descriptor ID
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_GET_DESCRIPTOR,
+                                4 + // Connection ID
+                                18 + // Service ID
+                                17 + // Characteristic ID
+                                1 + // Continuation
+                                17); // Start Descriptor ID
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aConnId),
                         aServiceId, aCharId,
                         PackConversion<bool, uint8_t>(aContinuation),
                         aStartDescriptorId, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientReadCharacteristicCmd(
   int aConnId, const BluetoothGattServiceId& aServiceId,
   const BluetoothGattId& aCharId, BluetoothGattAuthReq aAuthReq,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_READ_CHARACTERISTIC,
-                        4 + // Connection ID
-                        18 + // Service ID
-                        17 + // Characteristic ID
-                        4)); // Authorization
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_READ_CHARACTERISTIC,
+                                4 + // Connection ID
+                                18 + // Service ID
+                                17 + // Characteristic ID
+                                4); // Authorization
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aConnId), aServiceId,
                         aCharId, aAuthReq, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientWriteCharacteristicCmd(
   int aConnId, const BluetoothGattServiceId& aServiceId,
   const BluetoothGattId& aCharId, BluetoothGattWriteType aWriteType,
   int aLength, BluetoothGattAuthReq aAuthReq, char* aValue,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_WRITE_CHARACTERISTIC, 0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_WRITE_CHARACTERISTIC,
+                                0);
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aConnId), aServiceId,
                         aCharId, aWriteType,
                         PackConversion<int, int32_t>(aLength), aAuthReq,
                         PackArray<char>(aValue, aLength), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientReadDescriptorCmd(
   int aConnId, const BluetoothGattServiceId& aServiceId,
   const BluetoothGattId& aCharId, const BluetoothGattId& aDescriptorId,
   BluetoothGattAuthReq aAuthReq, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_READ_DESCRIPTOR,
-                        4 + // Connection ID
-                        18 + // Service ID
-                        17 + // Characteristic ID
-                        17 + // Descriptor ID
-                        4)); // Authorization
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_READ_DESCRIPTOR,
+                                4 + // Connection ID
+                                18 + // Service ID
+                                17 + // Characteristic ID
+                                17 + // Descriptor ID
+                                4); // Authorization
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aConnId), aServiceId,
                         aCharId, aDescriptorId, aAuthReq, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientWriteDescriptorCmd(
   int aConnId, const BluetoothGattServiceId& aServiceId,
   const BluetoothGattId& aCharId, const BluetoothGattId& aDescriptorId,
   BluetoothGattWriteType aWriteType, int aLength,
   BluetoothGattAuthReq aAuthReq, char* aValue,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_WRITE_DESCRIPTOR, 0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_WRITE_DESCRIPTOR,
+                                0);
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aConnId), aServiceId,
                         aCharId, aDescriptorId, aWriteType,
                         PackConversion<int, int32_t>(aLength), aAuthReq,
                         PackArray<char>(aValue, aLength), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientExecuteWriteCmd(
   int aConnId, int aIsExecute, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_EXECUTE_WRITE,
-                        4 + // Connection ID
-                        4)); // Execute
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_EXECUTE_WRITE,
+                                4 + // Connection ID
+                                4); // Execute
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aConnId),
                         PackConversion<int, int32_t>(aIsExecute), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientRegisterNotificationCmd(
   int aClientIf, const BluetoothAddress& aBdAddr,
   const BluetoothGattServiceId& aServiceId, const BluetoothGattId& aCharId,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_REGISTER_NOTIFICATION,
-                        4 + // Client Interface
-                        6 + // Remote Address
-                        18 + // Service ID
-                        17)); // Characteristic ID
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_REGISTER_NOTIFICATION,
+                                4 + // Client Interface
+                                6 + // Remote Address
+                                18 + // Service ID
+                                17); // Characteristic ID
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aClientIf),
                         aBdAddr, aServiceId, aCharId, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientDeregisterNotificationCmd(
   int aClientIf, const BluetoothAddress& aBdAddr,
   const BluetoothGattServiceId& aServiceId, const BluetoothGattId& aCharId,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_DEREGISTER_NOTIFICATION,
-                        4 + // Client Interface
-                        6 + // Remote Address
-                        18 + // Service ID
-                        17)); // Characteristic ID
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_DEREGISTER_NOTIFICATION,
+                                4 + // Client Interface
+                                6 + // Remote Address
+                                18 + // Service ID
+                                17); // Characteristic ID
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aClientIf),
                         aBdAddr, aServiceId, aCharId, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientReadRemoteRssiCmd(
   int aClientIf, const BluetoothAddress& aBdAddr,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_READ_REMOTE_RSSI,
-                        4 + // Client Interface
-                        6)); // Remote Address
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_READ_REMOTE_RSSI,
+                                4 + // Client Interface
+                                6); // Remote Address
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aClientIf),
                         aBdAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientGetDeviceTypeCmd(
   const BluetoothAddress& aBdAddr, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_GET_DEVICE_TYPE,
-                        6)); // Remote Address
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_GET_DEVICE_TYPE,
+                                6); // Remote Address
 
   nsresult rv = PackPDU(aBdAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientSetAdvDataCmd(
   int aServerIf, bool aIsScanRsp, bool aIsNameIncluded,
   bool aIsTxPowerIncluded, int aMinInterval, int aMaxInterval, int aApperance,
   const nsTArray<uint8_t>& aManufacturerData,
   const nsTArray<uint8_t>& aServiceData,
   const nsTArray<BluetoothUuid>& aServiceUuids,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_SET_ADV_DATA, 0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_SET_ADV_DATA,
+                                0);
 
   uint16_t manufacturerDataByteLen =
     aManufacturerData.Length() * sizeof(uint8_t);
   uint16_t serviceDataByteLen = aServiceData.Length() * sizeof(uint8_t);
   uint16_t serviceUuidsByteLen =
     aServiceUuids.Length() * sizeof(BluetoothUuid::mUuid);
   uint8_t* manufacturerData =
     const_cast<uint8_t*>(aManufacturerData.Elements());
@@ -621,410 +625,410 @@ BluetoothDaemonGattModule::ClientSetAdvD
     PackArray<uint8_t>(manufacturerData, aManufacturerData.Length()),
     PackArray<uint8_t>(serviceData, aServiceData.Length()),
     PackArray<PackReversed<BluetoothUuid>>(
       serviceUuids, aServiceUuids.Length()),
     *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ClientTestCommandCmd(
   int aCommand, const BluetoothGattTestParam& aTestParam,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLIENT_TEST_COMMAND,
-                        4 + // Command
-                        6 + // Address
-                        16 + // UUID
-                        2 + // U1
-                        2 + // U2
-                        2 + // U3
-                        2 + // U4
-                        2)); // U5
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLIENT_TEST_COMMAND,
+                                4 + // Command
+                                6 + // Address
+                                16 + // UUID
+                                2 + // U1
+                                2 + // U2
+                                2 + // U3
+                                2 + // U4
+                                2); // U5
 
   nsresult rv = PackPDU(
     PackConversion<int, int32_t>(aCommand),
     aTestParam.mBdAddr,
     aTestParam.mU1, aTestParam.mU2, aTestParam.mU3, aTestParam.mU4,
     aTestParam.mU5, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerRegisterCmd(
   const BluetoothUuid& aUuid, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_REGISTER,
-                        16)); // Uuid
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_REGISTER,
+                                16); // Uuid
 
   nsresult rv = PackPDU(aUuid, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerUnregisterCmd(
   int aServerIf, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_UNREGISTER,
-                        4)); // Server Interface
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_UNREGISTER,
+                                4); // Server Interface
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aServerIf), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerConnectPeripheralCmd(
   int aServerIf, const BluetoothAddress& aBdAddr, bool aIsDirect,
   BluetoothTransport aTransport, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_CONNECT_PERIPHERAL,
-                        4 + // Server Interface
-                        6 + // Remote Address
-                        1 + // Is Direct
-                        4)); // Transport
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_CONNECT_PERIPHERAL,
+                                4 + // Server Interface
+                                6 + // Remote Address
+                                1 + // Is Direct
+                                4); // Transport
 
   nsresult rv = PackPDU(
     PackConversion<int, int32_t>(aServerIf),
     aBdAddr,
     PackConversion<bool, uint8_t>(aIsDirect),
     PackConversion<BluetoothTransport, int32_t>(aTransport), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerDisconnectPeripheralCmd(
   int aServerIf, const BluetoothAddress& aBdAddr, int aConnId,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_DISCONNECT_PERIPHERAL,
-                        4 + // Server Interface
-                        6 + // Remote Address
-                        4)); // Connection Id
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_DISCONNECT_PERIPHERAL,
+                                4 + // Server Interface
+                                6 + // Remote Address
+                                4); // Connection Id
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aServerIf),
                         aBdAddr,
                         PackConversion<int, int32_t>(aConnId), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerAddServiceCmd(
   int aServerIf, const BluetoothGattServiceId& aServiceId, uint16_t aNumHandles,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_ADD_SERVICE,
-                        4 + // Server Interface
-                        18 + // Service ID
-                        4)); // Number of Handles
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_ADD_SERVICE,
+                                4 + // Server Interface
+                                18 + // Service ID
+                                4); // Number of Handles
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aServerIf), aServiceId,
                         PackConversion<uint16_t, int32_t>(aNumHandles), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerAddIncludedServiceCmd(
   int aServerIf, const BluetoothAttributeHandle& aServiceHandle,
   const BluetoothAttributeHandle& aIncludedServiceHandle,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_ADD_INCLUDED_SERVICE,
-                        4 + // Server Interface
-                        4 + // Service Handle
-                        4)); // Included Service Handle
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_ADD_INCLUDED_SERVICE,
+                                4 + // Server Interface
+                                4 + // Service Handle
+                                4); // Included Service Handle
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aServerIf),
                         aServiceHandle, aIncludedServiceHandle, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerAddCharacteristicCmd(
   int aServerIf, const BluetoothAttributeHandle& aServiceHandle,
   const BluetoothUuid& aUuid, BluetoothGattCharProp aProperties,
   BluetoothGattAttrPerm aPermissions, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_ADD_CHARACTERISTIC,
-                        4 + // Server Interface
-                        4 + // Service Handle
-                        16 + // UUID
-                        4 + // Properties
-                        4)); // Permissions
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_ADD_CHARACTERISTIC,
+                                4 + // Server Interface
+                                4 + // Service Handle
+                                16 + // UUID
+                                4 + // Properties
+                                4); // Permissions
 
   nsresult rv = PackPDU(
     PackConversion<int, int32_t>(aServerIf), aServiceHandle,
     PackReversed<BluetoothUuid>(aUuid),
     PackConversion<BluetoothGattCharProp, int32_t>(aProperties),
     PackConversion<BluetoothGattAttrPerm, int32_t>(aPermissions), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerAddDescriptorCmd(
   int aServerIf, const BluetoothAttributeHandle& aServiceHandle,
   const BluetoothUuid& aUuid, BluetoothGattAttrPerm aPermissions,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_ADD_DESCRIPTOR,
-                        4 + // Server Interface
-                        4 + // Service Handle
-                        16 + // UUID
-                        4)); // Permissions
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_ADD_DESCRIPTOR,
+                                4 + // Server Interface
+                                4 + // Service Handle
+                                16 + // UUID
+                                4); // Permissions
 
   nsresult rv = PackPDU(
     PackConversion<int, int32_t>(aServerIf), aServiceHandle,
     PackReversed<BluetoothUuid>(aUuid),
     PackConversion<BluetoothGattAttrPerm, int32_t>(aPermissions), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerStartServiceCmd(
   int aServerIf, const BluetoothAttributeHandle& aServiceHandle,
   BluetoothTransport aTransport, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_START_SERVICE,
-                        4 + // Server Interface
-                        4 + // Service Handle
-                        4)); // Transport
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_START_SERVICE,
+                                4 + // Server Interface
+                                4 + // Service Handle
+                                4); // Transport
 
   nsresult rv = PackPDU(
     PackConversion<int, int32_t>(aServerIf), aServiceHandle,
     PackConversion<BluetoothTransport, int32_t>(aTransport), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerStopServiceCmd(
   int aServerIf, const BluetoothAttributeHandle& aServiceHandle,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_STOP_SERVICE,
-                        4 + // Server Interface
-                        4)); // Service Handle
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_STOP_SERVICE,
+                                4 + // Server Interface
+                                4); // Service Handle
 
   nsresult rv = PackPDU(
     PackConversion<int, int32_t>(aServerIf), aServiceHandle, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerDeleteServiceCmd(
   int aServerIf, const BluetoothAttributeHandle& aServiceHandle,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_DELETE_SERVICE,
-                        4 + // Server Interface
-                        4)); // Service Handle
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_DELETE_SERVICE,
+                                4 + // Server Interface
+                                4); // Service Handle
 
   nsresult rv = PackPDU(
     PackConversion<int, int32_t>(aServerIf), aServiceHandle, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerSendIndicationCmd(
   int aServerIf, const BluetoothAttributeHandle& aCharacteristicHandle,
   int aConnId, int aLength, bool aConfirm,
   uint8_t* aValue, BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_SEND_INDICATION,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_SEND_INDICATION,
+                                0);
 
   nsresult rv = PackPDU(PackConversion<int, int32_t>(aServerIf),
                         aCharacteristicHandle,
                         PackConversion<int, int32_t>(aConnId),
                         PackConversion<int, int32_t>(aLength),
                         PackConversion<bool, int32_t>(aConfirm),
                         PackArray<uint8_t>(aValue, aLength), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonGattModule::ServerSendResponseCmd(
   int aConnId, int aTransId, uint16_t aStatus,
   const BluetoothGattResponse& aResponse,
   BluetoothGattResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SERVER_SEND_RESPONSE,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SERVER_SEND_RESPONSE,
+                                0);
 
   nsresult rv = PackPDU(
     PackConversion<int, int32_t>(aConnId),
     PackConversion<int, int32_t>(aTransId),
     PackConversion<BluetoothAttributeHandle, uint16_t>(aResponse.mHandle),
     aResponse.mOffset,
     PackConversion<BluetoothGattAuthReq, uint8_t>(aResponse.mAuthReq),
     PackConversion<uint16_t, int32_t>(aStatus),
     aResponse.mLength,
     PackArray<uint8_t>(aResponse.mValue, aResponse.mLength), *pdu);
 
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 // Responses
 //
 
 void
 BluetoothDaemonGattModule::ErrorRsp(
--- a/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "BluetoothDaemonHandsfreeInterface.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/unused.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 using namespace mozilla::ipc;
 
 //
 // Handsfree module
@@ -54,256 +55,256 @@ BluetoothDaemonHandsfreeModule::HandleSv
 //
 
 nsresult
 BluetoothDaemonHandsfreeModule::ConnectCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CONNECT,
-                           6)); // Address
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CONNECT,
+                                6); // Address
 
   nsresult rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::DisconnectCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_DISCONNECT,
-                           6)); // Address
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_DISCONNECT,
+                                6); // Address
 
   nsresult rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::ConnectAudioCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CONNECT_AUDIO,
-                           6)); // Address
+  UniquePtr<DaemonSocketPDU> pdu(
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CONNECT_AUDIO,
+                                6)); // Address
 
   nsresult rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::DisconnectAudioCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_DISCONNECT_AUDIO,
-                           6)); // Address
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_DISCONNECT_AUDIO,
+                                6); // Address
 
   nsresult rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::StartVoiceRecognitionCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_START_VOICE_RECOGNITION,
-                           6)); // Address (BlueZ 5.25)
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_START_VOICE_RECOGNITION,
+                                6); // Address (BlueZ 5.25)
 
   nsresult rv;
 #if ANDROID_VERSION >= 21
   rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
 #endif
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::StopVoiceRecognitionCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_STOP_VOICE_RECOGNITION,
-                           6)); // Address (BlueZ 5.25)
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_STOP_VOICE_RECOGNITION,
+                                6); // Address (BlueZ 5.25)
 
   nsresult rv;
 #if ANDROID_VERSION >= 21
   rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
 #endif
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::VolumeControlCmd(
   BluetoothHandsfreeVolumeType aType, int aVolume,
   const BluetoothAddress& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_VOLUME_CONTROL,
-                           1 + // Volume type
-                           1 + // Volume
-                           6)); // Address (BlueZ 5.25)
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_VOLUME_CONTROL,
+                                1 + // Volume type
+                                1 + // Volume
+                                6); // Address (BlueZ 5.25)
 
 #if ANDROID_VERSION >= 21
   nsresult rv = PackPDU(
     aType, PackConversion<int, uint8_t>(aVolume), aRemoteAddr, *pdu);
 #else
   nsresult rv = PackPDU(aType, PackConversion<int, uint8_t>(aVolume), *pdu);
 #endif
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::DeviceStatusNotificationCmd(
   BluetoothHandsfreeNetworkState aNtkState,
   BluetoothHandsfreeServiceType aSvcType, int aSignal, int aBattChg,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_DEVICE_STATUS_NOTIFICATION,
-                           1 + // Network state
-                           1 + // Service type
-                           1 + // Signal strength
-                           1)); // Battery level
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_DEVICE_STATUS_NOTIFICATION,
+                                1 + // Network state
+                                1 + // Service type
+                                1 + // Signal strength
+                                1); // Battery level
 
   nsresult rv = PackPDU(aNtkState, aSvcType,
                         PackConversion<int, uint8_t>(aSignal),
                         PackConversion<int, uint8_t>(aBattChg), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::CopsResponseCmd(
   const char* aCops, const BluetoothAddress& aRemoteAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_COPS_RESPONSE,
-                           0 + // Dynamically allocated
-                           6)); // Address (BlueZ 5.25)
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_COPS_RESPONSE,
+                                0 + // Dynamically allocated
+                                6); // Address (BlueZ 5.25)
 
 #if ANDROID_VERSION >= 21
   nsresult rv = PackPDU(PackCString0(nsDependentCString(aCops)), aRemoteAddr,
                         *pdu);
 #else
   nsresult rv = PackPDU(PackCString0(nsDependentCString(aCops)), *pdu);
 #endif
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::CindResponseCmd(
   int aSvc, int aNumActive, int aNumHeld,
   BluetoothHandsfreeCallState aCallSetupState,
   int aSignal, int aRoam, int aBattChg,
   const BluetoothAddress& aRemoteAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CIND_RESPONSE,
-                           1 + // Service
-                           1 + // # Active
-                           1 + // # Held
-                           1 + // Call state
-                           1 + // Signal strength
-                           1 + // Roaming
-                           1 + // Battery level
-                           6)); // Address (BlueZ 5.25)
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CIND_RESPONSE,
+                                1 + // Service
+                                1 + // # Active
+                                1 + // # Held
+                                1 + // Call state
+                                1 + // Signal strength
+                                1 + // Roaming
+                                1 + // Battery level
+                                6); // Address (BlueZ 5.25)
 
 #if ANDROID_VERSION >= 21
   nsresult rv = PackPDU(
     PackConversion<int, uint8_t>(aSvc),
     PackConversion<int, uint8_t>(aNumActive),
     PackConversion<int, uint8_t>(aNumHeld),
     aCallSetupState,
     PackConversion<int, uint8_t>(aSignal),
@@ -317,183 +318,183 @@ BluetoothDaemonHandsfreeModule::CindResp
                         aCallSetupState,
                         PackConversion<int, uint8_t>(aSignal),
                         PackConversion<int, uint8_t>(aRoam),
                         PackConversion<int, uint8_t>(aBattChg), *pdu);
 #endif
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::FormattedAtResponseCmd(
   const char* aRsp, const BluetoothAddress& aRemoteAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_FORMATTED_AT_RESPONSE,
-                           0 + // Dynamically allocated
-                           6)); // Address (BlueZ 5.25)
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_FORMATTED_AT_RESPONSE,
+                                0 + // Dynamically allocated
+                                6); // Address (BlueZ 5.25)
 
 #if ANDROID_VERSION >= 21
   nsresult rv = PackPDU(PackCString0(nsDependentCString(aRsp)), aRemoteAddr,
                                      *pdu);
 #else
   nsresult rv = PackPDU(PackCString0(nsDependentCString(aRsp)), *pdu);
 #endif
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::AtResponseCmd(
   BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
   const BluetoothAddress& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_AT_RESPONSE,
-                           1 + // AT Response code
-                           1 + // Error code
-                           6)); // Address (BlueZ 5.25)
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_AT_RESPONSE,
+                                1 + // AT Response code
+                                1 + // Error code
+                                6); // Address (BlueZ 5.25)
 
 #if ANDROID_VERSION >= 21
   nsresult rv = PackPDU(aResponseCode,
                         PackConversion<int, uint8_t>(aErrorCode),
                         aRemoteAddr, *pdu);
 #else
   nsresult rv = PackPDU(aResponseCode,
                         PackConversion<int, uint8_t>(aErrorCode), *pdu);
 #endif
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::ClccResponseCmd(
   int aIndex,
   BluetoothHandsfreeCallDirection aDir, BluetoothHandsfreeCallState aState,
   BluetoothHandsfreeCallMode aMode, BluetoothHandsfreeCallMptyType aMpty,
   const nsAString& aNumber, BluetoothHandsfreeCallAddressType aType,
   const BluetoothAddress& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ConvertUTF16toUTF8 number(aNumber);
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CLCC_RESPONSE,
-                           1 + // Call index
-                           1 + // Call direction
-                           1 + // Call state
-                           1 + // Call mode
-                           1 + // Call MPTY
-                           1 + // Address type
-                           number.Length() + 1 + // Number string + \0
-                           6)); // Address (BlueZ 5.25)
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CLCC_RESPONSE,
+                                1 + // Call index
+                                1 + // Call direction
+                                1 + // Call state
+                                1 + // Call mode
+                                1 + // Call MPTY
+                                1 + // Address type
+                                number.Length() + 1 + // Number string + \0
+                                6); // Address (BlueZ 5.25)
 
 #if ANDROID_VERSION >= 21
   nsresult rv = PackPDU(PackConversion<int, uint8_t>(aIndex),
                         aDir, aState, aMode, aMpty, aType,
                         PackCString0(number), aRemoteAddr, *pdu);
 #else
   nsresult rv = PackPDU(PackConversion<int, uint8_t>(aIndex),
                         aDir, aState, aMode, aMpty, aType,
                         PackCString0(number), *pdu);
 #endif
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::PhoneStateChangeCmd(
   int aNumActive, int aNumHeld, BluetoothHandsfreeCallState aCallSetupState,
   const nsAString& aNumber, BluetoothHandsfreeCallAddressType aType,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ConvertUTF16toUTF8 number(aNumber);
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_PHONE_STATE_CHANGE,
-                           1 + // # Active
-                           1 + // # Held
-                           1 + // Call state
-                           1 + // Address type
-                           number.Length() + 1)); // Number string + \0
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_PHONE_STATE_CHANGE,
+                                1 + // # Active
+                                1 + // # Held
+                                1 + // Call state
+                                1 + // Address type
+                                number.Length() + 1); // Number string + \0
 
   nsresult rv = PackPDU(PackConversion<int, uint8_t>(aNumActive),
                         PackConversion<int, uint8_t>(aNumHeld),
                         aCallSetupState, aType,
                         PackCString0(NS_ConvertUTF16toUTF8(aNumber)), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::ConfigureWbsCmd(
   const BluetoothAddress& aRemoteAddr,
   BluetoothHandsfreeWbsConfig aConfig,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CONFIGURE_WBS,
-                           6 + // Address
-                           1)); // Config
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CONFIGURE_WBS,
+                                6 + // Address
+                                1); // Config
 
   nsresult rv = PackPDU(aRemoteAddr, aConfig, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 // Responses
 //
 
 void
 BluetoothDaemonHandsfreeModule::ErrorRsp(
--- a/dom/bluetooth/bluedroid/BluetoothDaemonHidInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonHidInterface.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "BluetoothDaemonHidInterface.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/unused.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 using namespace mozilla::ipc;
 
 //
 // Hid module
@@ -49,215 +50,227 @@ BluetoothDaemonHidModule::HandleSvc(
 //
 
 nsresult
 BluetoothDaemonHidModule::ConnectCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothHidResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CONNECT, 6)); // Address
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CONNECT,
+                                6); // Address
 
   nsresult rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHidModule::DisconnectCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothHidResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_DISCONNECT, 6)); // Address
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_DISCONNECT,
+                                6); // Address
 
   nsresult rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHidModule::VirtualUnplugCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothHidResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_VIRTUAL_UNPLUG, 6)); // Address
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_VIRTUAL_UNPLUG,
+                                6); // Address
 
   nsresult rv = PackPDU(aRemoteAddr, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHidModule::SetInfoCmd(
   const BluetoothAddress& aRemoteAddr,
   const BluetoothHidInfoParam& aHidInfoParam,
   BluetoothHidResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_INFO, 0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SET_INFO,
+                                6 + // Address
+                                897); // Info
 
   nsresult rv = PackPDU(aRemoteAddr, aHidInfoParam, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHidModule::GetProtocolCmd(
   const BluetoothAddress& aRemoteAddr,
   BluetoothHidProtocolMode aHidProtocolMode,
   BluetoothHidResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_PROTOCOL,
-                        6 + // Address
-                        1)); // Protocol Mode
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_PROTOCOL,
+                                6 + // Address
+                                1); // Protocol Mode
 
   nsresult rv = PackPDU(aRemoteAddr, aHidProtocolMode, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHidModule::SetProtocolCmd(
   const BluetoothAddress& aRemoteAddr,
   BluetoothHidProtocolMode aHidProtocolMode,
   BluetoothHidResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_PROTOCOL,
-                        6 + // Remote Address
-                        1)); // Protocol Mode
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SET_PROTOCOL,
+                                6 + // Remote Address
+                                1); // Protocol Mode
 
   nsresult rv = PackPDU(aRemoteAddr, aHidProtocolMode, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHidModule::GetReportCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothHidReportType aType,
   uint8_t aReportId, uint16_t aBuffSize, BluetoothHidResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_REPORT,
-                        6 + // Address
-                        1 + // Report Type
-                        1 + // Report ID
-                        2)); // Buffer Size
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_GET_REPORT,
+                                6 + // Address
+                                1 + // Report Type
+                                1 + // Report ID
+                                2); // Buffer Size
 
   nsresult rv = PackPDU(aRemoteAddr, aType, aReportId, aBuffSize, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHidModule::SetReportCmd(
   const BluetoothAddress& aRemoteAddr, BluetoothHidReportType aType,
   const BluetoothHidReport& aReport, BluetoothHidResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_REPORT, 0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SET_REPORT,
+                                6 + // Address
+                                1 + // Type
+                                2 + // Length
+                                0); // Dynamically allocated
 
   nsresult rv = PackPDU(aRemoteAddr, aType, aReport, *pdu);
 
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHidModule::SendDataCmd(
   const BluetoothAddress& aRemoteAddr, uint16_t aDataLen, const uint8_t* aData,
   BluetoothHidResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_SEND_DATA, 0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_SEND_DATA,
+                                6 + // Address
+                                2 + // Length
+                                0); // Dynamically allocated
 
   nsresult rv = PackPDU(aRemoteAddr, aDataLen,
                         PackArray<uint8_t>(aData, aDataLen), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return NS_OK;
 }
 
 // Responses
 //
 
 void
 BluetoothDaemonHidModule::ErrorRsp(
--- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp
@@ -410,27 +410,27 @@ BluetoothDaemonInterface::Init(
   // If we could not cleanup properly before and an old
   // instance of the daemon is still running, we kill it
   // here.
   mozilla::hal::StopSystemService("bluetoothd");
 
   mResultHandlerQ.AppendElement(aRes);
 
   if (!mProtocol) {
-    mProtocol = new BluetoothDaemonProtocol();
+    mProtocol = MakeUnique<BluetoothDaemonProtocol>();
   }
 
   if (!mListenSocket) {
     mListenSocket = new ListenSocket(this, LISTEN_SOCKET);
   }
 
   // Init, step 1: Listen for command channel... */
 
   if (!mCmdChannel) {
-    mCmdChannel = new DaemonSocket(mProtocol, this, CMD_CHANNEL);
+    mCmdChannel = new DaemonSocket(mProtocol.get(), this, CMD_CHANNEL);
   } else if (
     NS_WARN_IF(mCmdChannel->GetConnectionStatus() == SOCKET_CONNECTED)) {
     // Command channel should not be open; let's close it.
     mCmdChannel->Close();
   }
 
   // The listen socket's name is generated with a random postfix. This
   // avoids naming collisions if we still have a listen socket from a
@@ -563,106 +563,107 @@ BluetoothDaemonInterface::DispatchError(
 
 // Service Interfaces
 //
 
 BluetoothSetupInterface*
 BluetoothDaemonInterface::GetBluetoothSetupInterface()
 {
   if (mSetupInterface) {
-    return mSetupInterface;
+    return mSetupInterface.get();
   }
 
-  mSetupInterface = new BluetoothDaemonSetupInterface(mProtocol);
+  mSetupInterface = MakeUnique<BluetoothDaemonSetupInterface>(mProtocol.get());
 
-  return mSetupInterface;
+  return mSetupInterface.get();
 }
 
 BluetoothCoreInterface*
 BluetoothDaemonInterface::GetBluetoothCoreInterface()
 {
   if (mCoreInterface) {
-    return mCoreInterface;
+    return mCoreInterface.get();
   }
 
-  mCoreInterface = new BluetoothDaemonCoreInterface(mProtocol);
+  mCoreInterface = MakeUnique<BluetoothDaemonCoreInterface>(mProtocol.get());
 
-  return mCoreInterface;
+  return mCoreInterface.get();
 }
 
 BluetoothSocketInterface*
 BluetoothDaemonInterface::GetBluetoothSocketInterface()
 {
   if (mSocketInterface) {
-    return mSocketInterface;
+    return mSocketInterface.get();
   }
 
-  mSocketInterface = new BluetoothDaemonSocketInterface(mProtocol);
+  mSocketInterface = MakeUnique<BluetoothDaemonSocketInterface>(mProtocol.get());
+
+  return mSocketInterface.get();
+}
 
-  return mSocketInterface;
+BluetoothHidInterface*
+BluetoothDaemonInterface::GetBluetoothHidInterface()
+{
+  if (mHidInterface) {
+    return mHidInterface.get();
+  }
+
+  mHidInterface = MakeUnique<BluetoothDaemonHidInterface>(mProtocol.get());
+
+  return mHidInterface.get();
 }
 
 BluetoothHandsfreeInterface*
 BluetoothDaemonInterface::GetBluetoothHandsfreeInterface()
 {
   if (mHandsfreeInterface) {
-    return mHandsfreeInterface;
+    return mHandsfreeInterface.get();
   }
 
-  mHandsfreeInterface = new BluetoothDaemonHandsfreeInterface(mProtocol);
+  mHandsfreeInterface =
+    MakeUnique<BluetoothDaemonHandsfreeInterface>(mProtocol.get());
 
-  return mHandsfreeInterface;
+  return mHandsfreeInterface.get();
 }
 
 BluetoothA2dpInterface*
 BluetoothDaemonInterface::GetBluetoothA2dpInterface()
 {
   if (mA2dpInterface) {
-    return mA2dpInterface;
+    return mA2dpInterface.get();
   }
 
-  mA2dpInterface = new BluetoothDaemonA2dpInterface(mProtocol);
+  mA2dpInterface = MakeUnique<BluetoothDaemonA2dpInterface>(mProtocol.get());
 
-  return mA2dpInterface;
+  return mA2dpInterface.get();
 }
 
 BluetoothAvrcpInterface*
 BluetoothDaemonInterface::GetBluetoothAvrcpInterface()
 {
   if (mAvrcpInterface) {
-    return mAvrcpInterface;
+    return mAvrcpInterface.get();
   }
 
-  mAvrcpInterface = new BluetoothDaemonAvrcpInterface(mProtocol);
+  mAvrcpInterface = MakeUnique<BluetoothDaemonAvrcpInterface>(mProtocol.get());
 
-  return mAvrcpInterface;
+  return mAvrcpInterface.get();
 }
 
 BluetoothGattInterface*
 BluetoothDaemonInterface::GetBluetoothGattInterface()
 {
   if (mGattInterface) {
-    return mGattInterface;
+    return mGattInterface.get();
   }
 
-  mGattInterface = new BluetoothDaemonGattInterface(mProtocol);
-
-  return mGattInterface;
-}
+  mGattInterface = MakeUnique<BluetoothDaemonGattInterface>(mProtocol.get());
 
-BluetoothHidInterface*
-BluetoothDaemonInterface::GetBluetoothHidInterface()
-{
-  if (mHidInterface) {
-    return mHidInterface;
-  }
-
-  mHidInterface = new BluetoothDaemonHidInterface(mProtocol);
-
-  return mHidInterface;
+  return mGattInterface.get();
 }
 
 // |DaemonSocketConsumer|, |ListenSocketConsumer|
 
 void
 BluetoothDaemonInterface::OnConnectSuccess(int aIndex)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -674,17 +675,17 @@ BluetoothDaemonInterface::OnConnectSucce
         nsCString args("-a ");
         args.Append(mListenSocketName);
         mozilla::hal::StartSystemService("bluetoothd", args.get());
       }
       break;
     case CMD_CHANNEL:
       // Init, step 3: Listen for notification channel...
       if (!mNtfChannel) {
-        mNtfChannel = new DaemonSocket(mProtocol, this, NTF_CHANNEL);
+        mNtfChannel = new DaemonSocket(mProtocol.get(), this, NTF_CHANNEL);
       } else if (
         NS_WARN_IF(mNtfChannel->GetConnectionStatus() == SOCKET_CONNECTED)) {
         /* Notification channel should not be open; let's close it. */
         mNtfChannel->Close();
       }
       if (NS_FAILED(mListenSocket->Listen(mNtfChannel))) {
         OnConnectError(NTF_CHANNEL);
       }
--- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluedroid_BluetoothDaemonInterface_h
 #define mozilla_dom_bluetooth_bluedroid_BluetoothDaemonInterface_h
 
 #include "BluetoothInterface.h"
 #include "mozilla/ipc/DaemonSocketConsumer.h"
 #include "mozilla/ipc/ListenSocketConsumer.h"
+#include "mozilla/UniquePtr.h"
 
 namespace mozilla {
 namespace ipc {
 
 class DaemonSocket;
 class ListenSocket;
 
 }
@@ -83,25 +84,25 @@ private:
   void DispatchError(BluetoothResultHandler* aRes, nsresult aRv);
 
   static BluetoothNotificationHandler* sNotificationHandler;
 
   nsCString mListenSocketName;
   RefPtr<mozilla::ipc::ListenSocket> mListenSocket;
   RefPtr<mozilla::ipc::DaemonSocket> mCmdChannel;
   RefPtr<mozilla::ipc::DaemonSocket> mNtfChannel;
-  nsAutoPtr<BluetoothDaemonProtocol> mProtocol;
+  UniquePtr<BluetoothDaemonProtocol> mProtocol;
 
   nsTArray<RefPtr<BluetoothResultHandler> > mResultHandlerQ;
 
-  nsAutoPtr<BluetoothDaemonSetupInterface> mSetupInterface;
-  nsAutoPtr<BluetoothDaemonCoreInterface> mCoreInterface;
-  nsAutoPtr<BluetoothDaemonSocketInterface> mSocketInterface;
-  nsAutoPtr<BluetoothDaemonHandsfreeInterface> mHandsfreeInterface;
-  nsAutoPtr<BluetoothDaemonA2dpInterface> mA2dpInterface;
-  nsAutoPtr<BluetoothDaemonAvrcpInterface> mAvrcpInterface;
-  nsAutoPtr<BluetoothDaemonGattInterface> mGattInterface;
-  nsAutoPtr<BluetoothDaemonHidInterface> mHidInterface;
+  UniquePtr<BluetoothDaemonSetupInterface> mSetupInterface;
+  UniquePtr<BluetoothDaemonCoreInterface> mCoreInterface;
+  UniquePtr<BluetoothDaemonSocketInterface> mSocketInterface;
+  UniquePtr<BluetoothDaemonHidInterface> mHidInterface;
+  UniquePtr<BluetoothDaemonHandsfreeInterface> mHandsfreeInterface;
+  UniquePtr<BluetoothDaemonA2dpInterface> mA2dpInterface;
+  UniquePtr<BluetoothDaemonAvrcpInterface> mAvrcpInterface;
+  UniquePtr<BluetoothDaemonGattInterface> mGattInterface;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif // mozilla_dom_bluetooth_bluedroid_BluetoothDaemonInterface_h
--- a/dom/bluetooth/bluedroid/BluetoothDaemonSetupInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonSetupInterface.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "BluetoothDaemonSetupInterface.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/unused.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 using namespace mozilla::ipc;
 
 //
 // Setup module
@@ -56,79 +57,79 @@ BluetoothDaemonSetupModule::HandleSvc(co
 
 nsresult
 BluetoothDaemonSetupModule::RegisterModuleCmd(
   BluetoothSetupServiceId aId, uint8_t aMode, uint32_t aMaxNumClients,
   BluetoothSetupResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_REGISTER_MODULE,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_REGISTER_MODULE,
+                                0);
 
 #if ANDROID_VERSION >= 21
   nsresult rv = PackPDU(aId, aMode, aMaxNumClients, *pdu);
 #else
   nsresult rv = PackPDU(aId, aMode, *pdu);
 #endif
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonSetupModule::UnregisterModuleCmd(
   BluetoothSetupServiceId aId, BluetoothSetupResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_UNREGISTER_MODULE,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_UNREGISTER_MODULE,
+                                0);
 
   nsresult rv = PackPDU(aId, *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonSetupModule::ConfigurationCmd(
   const BluetoothConfigurationParameter* aParam, uint8_t aLen,
   BluetoothSetupResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CONFIGURATION,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CONFIGURATION,
+                                0);
 
   nsresult rv = PackPDU(
     aLen, PackArray<BluetoothConfigurationParameter>(aParam, aLen), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 // Responses
 //
 
 void
 BluetoothDaemonSetupModule::ErrorRsp(const DaemonSocketPDUHeader& aHeader,
--- a/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.cpp
@@ -1,18 +1,19 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "BluetoothDaemonSocketInterface.h"
 #include "BluetoothSocketMessageWatcher.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/unused.h"
 #include "nsXULAppAPI.h"
-#include "mozilla/unused.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 using namespace mozilla::ipc;
 
 //
 // Socket module
 //
@@ -27,65 +28,65 @@ BluetoothDaemonSocketModule::ListenCmd(B
                                        const BluetoothServiceName& aServiceName,
                                        const BluetoothUuid& aServiceUuid,
                                        int aChannel, bool aEncrypt,
                                        bool aAuth,
                                        BluetoothSocketResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_LISTEN,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_LISTEN,
+                                0);
 
   nsresult rv = PackPDU(
     aType,
     aServiceName,
     aServiceUuid,
     PackConversion<int, int32_t>(aChannel),
     SocketFlags(aEncrypt, aAuth), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 nsresult
 BluetoothDaemonSocketModule::ConnectCmd(const BluetoothAddress& aBdAddr,
                                         BluetoothSocketType aType,
                                         const BluetoothUuid& aServiceUuid,
                                         int aChannel, bool aEncrypt,
                                         bool aAuth,
                                         BluetoothSocketResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  nsAutoPtr<DaemonSocketPDU> pdu(
-    new DaemonSocketPDU(SERVICE_ID, OPCODE_CONNECT,
-                        0));
+  UniquePtr<DaemonSocketPDU> pdu =
+    MakeUnique<DaemonSocketPDU>(SERVICE_ID, OPCODE_CONNECT,
+                                0);
 
   nsresult rv = PackPDU(
     aBdAddr,
     aType,
     aServiceUuid,
     PackConversion<int, int32_t>(aChannel),
     SocketFlags(aEncrypt, aAuth), *pdu);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  rv = Send(pdu, aRes);
+  rv = Send(pdu.get(), aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
-  Unused << pdu.forget();
+  Unused << pdu.release();
   return rv;
 }
 
 /* |DeleteTask| deletes a class instance on the I/O thread
  */
 template <typename T>
 class DeleteTask final : public Task
 {
@@ -95,17 +96,17 @@ public:
   { }
 
   void Run() override
   {
     mPtr = nullptr;
   }
 
 private:
-  nsAutoPtr<T> mPtr;
+  UniquePtr<T> mPtr;
 };
 
 /* |AcceptWatcher| specializes SocketMessageWatcher for Accept
  * operations by reading the socket messages from Bluedroid and
  * forwarding the received client socket to the resource handler.
  * The first message is received immediately. When there's a new
  * connection, Bluedroid sends the 2nd message with the socket
  * info and socket file descriptor.
--- a/dom/bluetooth/bluedroid/BluetoothHidManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothHidManager.cpp
@@ -9,16 +9,32 @@
 #include "BluetoothUtils.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIObserverService.h"
 
 using namespace mozilla;
 USING_BLUETOOTH_NAMESPACE
 
+#define ENSURE_HID_DEV_IS_CONNECTED                                           \
+  do {                                                                        \
+    if(!IsConnected()) {                                                      \
+      BT_LOGR("Device is not connected");                                     \
+      return;                                                                 \
+    }                                                                         \
+  } while(0)                                                                  \
+
+#define ENSURE_HID_INTF_IS_EXISTED                                            \
+  do {                                                                        \
+    if(!sBluetoothHidInterface) {                                             \
+      BT_LOGR("sBluetoothHidInterface is null");                              \
+      return;                                                                 \
+    }                                                                         \
+  } while(0)                                                                  \
+
 namespace {
   StaticRefPtr<BluetoothHidManager> sBluetoothHidManager;
   static BluetoothHidInterface* sBluetoothHidInterface = nullptr;
   bool sInShutdown = false;
 } // namesapce
 
 const int BluetoothHidManager::MAX_NUM_CLIENTS = 1;
 
@@ -518,16 +534,108 @@ BluetoothHidManager::OnDisconnect(const 
    * connections. On the other hand, we do nothing for inbound connections.
    */
   NS_ENSURE_TRUE_VOID(mController);
 
   mController->NotifyCompletion(aErrorStr);
   Reset();
 }
 
+class BluetoothHidManager::VirtualUnplugResultHandler final
+  : public BluetoothHidResultHandler
+{
+public:
+  void OnError(BluetoothStatus aStatus) override
+  {
+    BT_WARNING("BluetoothHidInterface::VirtualUnplug failed: %d", (int)aStatus);
+  }
+};
+
+void
+BluetoothHidManager::VirtualUnplug()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  ENSURE_HID_DEV_IS_CONNECTED;
+  MOZ_ASSERT(!mDeviceAddress.IsCleared());
+  ENSURE_HID_INTF_IS_EXISTED;
+
+  sBluetoothHidInterface->VirtualUnplug(
+    mDeviceAddress, new VirtualUnplugResultHandler());
+}
+
+class BluetoothHidManager::GetReportResultHandler final
+  : public BluetoothHidResultHandler
+{
+public:
+  void OnError(BluetoothStatus aStatus) override
+  {
+    BT_WARNING("BluetoothHidInterface::GetReport failed: %d", (int)aStatus);
+  }
+};
+
+void
+BluetoothHidManager::GetReport(const BluetoothHidReportType& aReportType,
+                               const uint8_t aReportId,
+                               const uint16_t aBufSize)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  ENSURE_HID_DEV_IS_CONNECTED;
+  MOZ_ASSERT(!mDeviceAddress.IsCleared());
+  ENSURE_HID_INTF_IS_EXISTED;
+
+  sBluetoothHidInterface->GetReport(
+    mDeviceAddress, aReportType, aReportId, aBufSize,
+    new GetReportResultHandler());
+}
+
+class BluetoothHidManager::SetReportResultHandler final
+  : public BluetoothHidResultHandler
+{
+public:
+  void OnError(BluetoothStatus aStatus) override
+  {
+    BT_WARNING("BluetoothHidInterface::SetReport failed: %d", (int)aStatus);
+  }
+};
+
+void
+BluetoothHidManager::SetReport(const BluetoothHidReportType& aReportType,
+                               const BluetoothHidReport& aReport)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  ENSURE_HID_DEV_IS_CONNECTED;
+  MOZ_ASSERT(!mDeviceAddress.IsCleared());
+  ENSURE_HID_INTF_IS_EXISTED;
+
+  sBluetoothHidInterface->SetReport(
+    mDeviceAddress, aReportType, aReport, new SetReportResultHandler());
+}
+
+class BluetoothHidManager::SendDataResultHandler final
+  : public BluetoothHidResultHandler
+{
+public:
+  void OnError(BluetoothStatus aStatus) override
+  {
+    BT_WARNING("BluetoothHidInterface::SendData failed: %d", (int)aStatus);
+  }
+};
+
+void
+BluetoothHidManager::SendData(const uint16_t aDataLen, const uint8_t* aData)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  ENSURE_HID_DEV_IS_CONNECTED;
+  MOZ_ASSERT(!mDeviceAddress.IsCleared());
+  ENSURE_HID_INTF_IS_EXISTED;
+
+  sBluetoothHidInterface->SendData(
+    mDeviceAddress, aDataLen, aData, new SendDataResultHandler());
+}
+
 void
 BluetoothHidManager::HandleShutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   sInShutdown = true;
   Disconnect(nullptr);
   sBluetoothHidManager = nullptr;
 }
--- a/dom/bluetooth/bluedroid/BluetoothHidManager.h
+++ b/dom/bluetooth/bluedroid/BluetoothHidManager.h
@@ -30,28 +30,39 @@ public:
     aName.AssignLiteral("HID");
   }
 
   static BluetoothHidManager* Get();
   static void InitHidInterface(BluetoothProfileResultHandler* aRes);
   static void DeinitHidInterface(BluetoothProfileResultHandler* aRes);
 
   void HandleBackendError();
+  void GetReport(const BluetoothHidReportType& aReportType,
+                 const uint8_t aReportId,
+                 const uint16_t aBufSize);
+  void SendData(const uint16_t aDataLen, const uint8_t* aData);
+  void SetReport(const BluetoothHidReportType& aReportType,
+                 const BluetoothHidReport& aReport);
+  void VirtualUnplug();
 
 protected:
   virtual ~BluetoothHidManager();
 
 private:
   class DeinitProfileResultHandlerRunnable;
   class InitProfileResultHandlerRunnable;
   class RegisterModuleResultHandler;
   class UnregisterModuleResultHandler;
 
   class ConnectResultHandler;
   class DisconnectResultHandler;
+  class GetReportResultHandler;
+  class SendDataResultHandler;
+  class SetReportResultHandler;
+  class VirtualUnplugResultHandler;
 
   BluetoothHidManager();
   void Uninit();
   void HandleShutdown();
   void NotifyConnectionStateChanged(const nsAString& aType);
 
   //
   // Bluetooth notifications
--- a/dom/bluetooth/bluedroid/BluetoothMapBMessage.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothMapBMessage.cpp
@@ -1,13 +1,14 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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 "BluetoothMapBMessage.h"
 #include "base/basictypes.h"
 #include "plstr.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 namespace {
   static const char kMapCrlf[] = "\r\n";
--- a/dom/bluetooth/bluedroid/BluetoothMapBMessage.h
+++ b/dom/bluetooth/bluedroid/BluetoothMapBMessage.h
@@ -3,17 +3,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluedroid_BluetoothMapBMessage_h
 #define mozilla_dom_bluetooth_bluedroid_BluetoothMapBMessage_h
 
 #include "BluetoothCommon.h"
-#include "nsAutoPtr.h"
 #include "nsRefPtrHashtable.h"
 #include "nsTArray.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 enum BMsgParserState {
   BMSG_PARSING_STATE_INVALID,
   BMSG_PARSING_STATE_BEGIN_BMSG,
--- a/dom/bluetooth/bluedroid/BluetoothMapFolder.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothMapFolder.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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 "BluetoothMapFolder.h"
 #include "base/basictypes.h"
-#include "BluetoothMapFolder.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 BluetoothMapFolder::~BluetoothMapFolder()
 { }
 
 BluetoothMapFolder::BluetoothMapFolder(const nsAString& aFolderName,
                                        BluetoothMapFolder* aParent)
--- a/dom/bluetooth/bluedroid/BluetoothMapFolder.h
+++ b/dom/bluetooth/bluedroid/BluetoothMapFolder.h
@@ -3,17 +3,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluedroid_BluetoothMapFolder_h
 #define mozilla_dom_bluetooth_bluedroid_BluetoothMapFolder_h
 
 #include "BluetoothCommon.h"
-#include "nsAutoPtr.h"
 #include "nsRefPtrHashtable.h"
 #include "nsTArray.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 /* This class maps MAP virtual folder structures */
 class BluetoothMapFolder
 {
--- a/dom/bluetooth/bluedroid/BluetoothMapSmsManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothMapSmsManager.cpp
@@ -16,17 +16,16 @@
 #include "mozilla/dom/BluetoothMapParametersBinding.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/Endian.h"
 #include "mozilla/dom/File.h"
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
-#include "nsAutoPtr.h"
 #include "nsIInputStream.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 
 #define FILTER_NO_SMS_GSM   0x01
 #define FILTER_NO_SMS_CDMA  0x02
 #define FILTER_NO_EMAIL     0x04
 #define FILTER_NO_MMS       0x08
@@ -453,24 +452,24 @@ BluetoothMapSmsManager::MasDataHandler(U
       BT_LOGR("Unrecognized ObexRequestCode %x", opCode);
       break;
   }
 }
 
 // Virtual function of class SocketConsumer
 void
 BluetoothMapSmsManager::ReceiveSocketData(BluetoothSocket* aSocket,
-                                          nsAutoPtr<UnixSocketBuffer>& aMessage)
+                                          UniquePtr<UnixSocketBuffer>& aMessage)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (aSocket == mMnsSocket) {
-    MnsDataHandler(aMessage);
+    MnsDataHandler(aMessage.get());
   } else {
-    MasDataHandler(aMessage);
+    MasDataHandler(aMessage.get());
   }
 }
 
 bool
 BluetoothMapSmsManager::CompareHeaderTarget(const ObexHeaderSet& aHeader)
 {
   const ObexHeader* header = aHeader.GetHeader(ObexHeaderId::Target);
 
--- a/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
@@ -15,17 +15,16 @@
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/UniquePtr.h"
-#include "nsAutoPtr.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
 #include "nsIMIMEService.h"
 #include "nsIOutputStream.h"
 #include "nsIVolumeService.h"
@@ -1222,22 +1221,22 @@ BluetoothOppManager::ClientDataHandler(U
   } else {
     BT_WARNING("Unhandled ObexRequestCode");
   }
 }
 
 // Virtual function of class SocketConsumer
 void
 BluetoothOppManager::ReceiveSocketData(BluetoothSocket* aSocket,
-                                       nsAutoPtr<UnixSocketBuffer>& aBuffer)
+                                       UniquePtr<UnixSocketBuffer>& aBuffer)
 {
   if (mIsServer) {
-    ServerDataHandler(aBuffer);
+    ServerDataHandler(aBuffer.get());
   } else {
-    ClientDataHandler(aBuffer);
+    ClientDataHandler(aBuffer.get());
   }
 }
 
 void
 BluetoothOppManager::SendConnectRequest()
 {
   if (mConnected) {
     return;
--- a/dom/bluetooth/bluedroid/BluetoothPbapManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothPbapManager.cpp
@@ -14,17 +14,16 @@
 
 #include "mozilla/dom/BluetoothPbapParametersBinding.h"
 #include "mozilla/Endian.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
-#include "nsAutoPtr.h"
 #include "nsIInputStream.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsNetCID.h"
 
 USING_BLUETOOTH_NAMESPACE
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -253,17 +252,17 @@ BluetoothPbapManager::Listen()
 
   BT_LOGR("PBAP socket is listening");
   return true;
 }
 
 // Virtual function of class SocketConsumer
 void
 BluetoothPbapManager::ReceiveSocketData(BluetoothSocket* aSocket,
-                                        nsAutoPtr<UnixSocketBuffer>& aMessage)
+                                        UniquePtr<UnixSocketBuffer>& aMessage)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   /**
    * Ensure
    * - valid access to data[0], i.e., opCode
    * - received packet length smaller than max packet length
    */
--- a/dom/bluetooth/bluedroid/BluetoothSocket.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothSocket.cpp
@@ -184,17 +184,17 @@ private:
    */
   bool mShuttingDownOnIOThread;
 
   ConnectionStatus mConnectionStatus;
 
   /**
    * I/O buffer for received data
    */
-  nsAutoPtr<UnixSocketRawData> mBuffer;
+  UniquePtr<UnixSocketRawData> mBuffer;
 };
 
 class SocketConnectTask final : public SocketIOTask<DroidSocketImpl>
 {
 public:
   SocketConnectTask(DroidSocketImpl* aDroidSocketImpl, int aFd)
   : SocketIOTask<DroidSocketImpl>(aDroidSocketImpl)
   , mFd(aFd)
@@ -495,17 +495,17 @@ DroidSocketImpl::OnSocketCanConnectWitho
 
 nsresult
 DroidSocketImpl::QueryReceiveBuffer(
   UnixSocketIOBuffer** aBuffer)
 {
   MOZ_ASSERT(aBuffer);
 
   if (!mBuffer) {
-    mBuffer = new UnixSocketRawData(MAX_READ_SIZE);
+    mBuffer = MakeUnique<UnixSocketRawData>(MAX_READ_SIZE);
   }
   *aBuffer = mBuffer.get();
 
   return NS_OK;
 }
 
 /**
  * |ReceiveRunnable| transfers data received on the I/O thread
@@ -533,24 +533,24 @@ public:
 
     BluetoothSocket* bluetoothSocket = io->GetBluetoothSocket();
     MOZ_ASSERT(bluetoothSocket);
 
     bluetoothSocket->ReceiveSocketData(mBuffer);
   }
 
 private:
-  nsAutoPtr<UnixSocketBuffer> mBuffer;
+  UniquePtr<UnixSocketBuffer> mBuffer;
 };
 
 void
 DroidSocketImpl::ConsumeBuffer()
 {
   GetConsumerThread()->PostTask(FROM_HERE,
-                                new ReceiveTask(this, mBuffer.forget()));
+                                new ReceiveTask(this, mBuffer.release()));
 }
 
 void
 DroidSocketImpl::DiscardBuffer()
 {
   // Nothing to do.
 }
 
@@ -754,17 +754,17 @@ BluetoothSocket::Accept(int aListenFd, B
 
   SetCurrentResultHandler(aRes);
   mSocketInterface->Accept(aListenFd, aRes);
 
   return NS_OK;
 }
 
 void
-BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
+BluetoothSocket::ReceiveSocketData(UniquePtr<UnixSocketBuffer>& aBuffer)
 {
   if (mObserver) {
     mObserver->ReceiveSocketData(this, aBuffer);
   }
 }
 
 // |DataSocket|
 
--- a/dom/bluetooth/bluedroid/BluetoothSocket.h
+++ b/dom/bluetooth/bluedroid/BluetoothSocket.h
@@ -58,17 +58,17 @@ public:
   nsresult Accept(int aListenFd, BluetoothSocketResultHandler* aRes);
 
   /**
    * Method to be called whenever data is received. This is only called on the
    * consumer thread.
    *
    * @param aBuffer Data received from the socket.
    */
-  void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketBuffer>& aBuffer);
+  void ReceiveSocketData(UniquePtr<mozilla::ipc::UnixSocketBuffer>& aBuffer);
 
   inline void GetAddress(BluetoothAddress& aDeviceAddress)
   {
     aDeviceAddress = mDeviceAddress;
   }
 
   inline void SetAddress(const BluetoothAddress& aDeviceAddress)
   {
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -253,17 +253,17 @@ BluetoothHfpManager::Init()
   }
 
   hal::RegisterBatteryObserver(this);
   // Update to the latest battery level
   hal::BatteryInformation batteryInfo;
   hal::GetCurrentBatteryInformation(&batteryInfo);
   Notify(batteryInfo);
 
-  mListener = new BluetoothRilListener();
+  mListener = MakeUnique<BluetoothRilListener>();
   NS_ENSURE_TRUE(mListener->Listen(true), false);
 
   nsCOMPtr<nsISettingsService> settings =
     do_GetService("@mozilla.org/settingsService;1");
   NS_ENSURE_TRUE(settings, false);
 
   nsCOMPtr<nsISettingsServiceLock> settingsLock;
   nsresult rv = settings->CreateLock(nullptr, getter_AddRefs(settingsLock));
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
@@ -222,17 +222,17 @@ private:
   bool mDialingRequestProcessed;
   bool mNrecEnabled;
   PhoneType mPhoneType;
   BluetoothAddress mDeviceAddress;
   nsString mMsisdn;
   nsString mOperatorName;
 
   nsTArray<Call> mCurrentCallArray;
-  nsAutoPtr<BluetoothRilListener> mListener;
+  UniquePtr<BluetoothRilListener> mListener;
   RefPtr<BluetoothProfileController> mController;
 
   // CDMA-specific variable
   Call mCdmaSecondCall;
 };
 
 END_BLUETOOTH_NAMESPACE
 
--- a/dom/bluetooth/bluez/BluetoothDBusService.cpp
+++ b/dom/bluetooth/bluez/BluetoothDBusService.cpp
@@ -28,17 +28,16 @@
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothUnixSocketConnector.h"
 #include "BluetoothUtils.h"
 #include "BluetoothUuidHelper.h"
 
 #include <cstdio>
 #include <dbus/dbus.h>
 
-#include "nsAutoPtr.h"
 #include "nsThreadUtils.h"
 #include "nsDebug.h"
 #include "nsDataHashtable.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/Hal.h"
@@ -1272,17 +1271,17 @@ public:
 
   void Run() override
   {
     MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
     MOZ_ASSERT(sDBusConnection);
 
     nsAutoString errorStr;
     BluetoothValue v = true;
-    DBusMessage *msg;
+    DBusMessage *msg = nullptr;
 
     if (!sPairingReqTable->Get(mDeviceAddress, &msg) && mRunnable) {
       BT_WARNING("%s: Couldn't get original request message.", __FUNCTION__);
       errorStr.AssignLiteral("Couldn't get original request message.");
       DispatchBluetoothReply(mRunnable, v, errorStr);
 
       return;
     }
@@ -2106,17 +2105,17 @@ public:
     }
 
     mConnection->Watch();
 
     if (!sPairingReqTable) {
       sPairingReqTable = new nsDataHashtable<BluetoothAddressHashKey, DBusMessage* >;
     }
 
-    sDBusConnection = mConnection.forget();
+    sDBusConnection = mConnection.release();
 
     RefPtr<nsRunnable> runnable =
       new BluetoothService::ToggleBtAck(true);
     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
       BT_WARNING("Failed to dispatch to main thread!");
       return;
     }
 
@@ -2135,17 +2134,17 @@ public:
                                                     DBUS_TYPE_INVALID);
       if (!success) {
         BT_WARNING("Failed to query default adapter!");
       }
     }
   }
 
 private:
-  nsAutoPtr<RawDBusConnection> mConnection;
+  UniquePtr<RawDBusConnection> mConnection;
 };
 
 class StartBluetoothRunnable final : public nsRunnable
 {
 public:
   NS_IMETHOD Run()
   {
     // This could block. It should never be run on the main thread.
--- a/dom/bluetooth/bluez/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluez/BluetoothHfpManager.cpp
@@ -442,17 +442,17 @@ BluetoothHfpManager::Init()
 
   hal::RegisterBatteryObserver(this);
   // Update to the latest battery level
   hal::BatteryInformation batteryInfo;
   hal::GetCurrentBatteryInformation(&batteryInfo);
   Notify(batteryInfo);
 
 #ifdef MOZ_B2G_RIL
-  mListener = new BluetoothRilListener();
+  mListener = MakeUnique<BluetoothRilListener>();
   if (!mListener->Listen(true)) {
     BT_WARNING("Failed to start listening RIL");
     return false;
   }
 #endif
 
   nsCOMPtr<nsISettingsService> settings =
     do_GetService("@mozilla.org/settingsService;1");
@@ -728,17 +728,17 @@ BluetoothHfpManager::ParseAtCommand(cons
 
   nsCString tmp(nsDependentCSubstring(aAtCommand, begin));
   aRetValues.AppendElement(tmp);
 }
 
 // Virtual function of class SocketConsumer
 void
 BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,
-                                       nsAutoPtr<UnixSocketBuffer>& aMessage)
+                                       UniquePtr<UnixSocketBuffer>& aMessage)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aSocket);
 
   nsAutoCString msg(reinterpret_cast<const char*>(aMessage->GetData()),
                     aMessage->GetSize());
   msg.StripWhitespace();
 
--- a/dom/bluetooth/bluez/BluetoothHfpManager.h
+++ b/dom/bluetooth/bluez/BluetoothHfpManager.h
@@ -198,17 +198,17 @@ private:
   bool mDialingRequestProcessed;
 #endif
   BluetoothAddress mDeviceAddress;
 #ifdef MOZ_B2G_RIL
   nsString mMsisdn;
   nsString mOperatorName;
 
   nsTArray<Call> mCurrentCallArray;
-  nsAutoPtr<BluetoothRilListener> mListener;
+  UniquePtr<BluetoothRilListener> mListener;
 #endif
   RefPtr<BluetoothProfileController> mController;
   RefPtr<BluetoothReplyRunnable> mScoRunnable;
 
   // If a connection has been established, mSocket will be the socket
   // communicating with the remote socket. We maintain the invariant that if
   // mSocket is non-null, mHandsfreeSocket and mHeadsetSocket must be null (and
   // vice versa).
--- a/dom/bluetooth/bluez/BluetoothOppManager.cpp
+++ b/dom/bluetooth/bluez/BluetoothOppManager.cpp
@@ -15,17 +15,16 @@
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/UniquePtr.h"
-#include "nsAutoPtr.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
 #include "nsIMIMEService.h"
 #include "nsIOutputStream.h"
 #include "nsIVolumeService.h"
@@ -1139,22 +1138,22 @@ BluetoothOppManager::ClientDataHandler(U
   } else {
     BT_WARNING("Unhandled ObexRequestCode");
   }
 }
 
 // Virtual function of class SocketConsumer
 void
 BluetoothOppManager::ReceiveSocketData(BluetoothSocket* aSocket,
-                                       nsAutoPtr<UnixSocketBuffer>& aMessage)
+                                       UniquePtr<UnixSocketBuffer>& aMessage)
 {
   if (mIsServer) {
-    ServerDataHandler(aMessage);
+    ServerDataHandler(aMessage.get());
   } else {
-    ClientDataHandler(aMessage);
+    ClientDataHandler(aMessage.get());
   }
 }
 
 void
 BluetoothOppManager::SendConnectRequest()
 {
   if (mConnected) return;
 
--- a/dom/bluetooth/bluez/BluetoothSocket.cpp
+++ b/dom/bluetooth/bluez/BluetoothSocket.cpp
@@ -7,16 +7,17 @@
 #include "BluetoothSocket.h"
 #include <fcntl.h>
 #include "BluetoothSocketObserver.h"
 #include "BluetoothUnixSocketConnector.h"
 #include "BluetoothUtils.h"
 #include "mozilla/RefPtr.h"
 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR
 #include "nsXULAppAPI.h"
+#include "mozilla/unused.h"
 
 using namespace mozilla::ipc;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 static const size_t MAX_READ_SIZE = 1 << 16;
 
 //
@@ -99,17 +100,17 @@ private:
    * directly from consumer thread. All non-consumer-thread accesses should
    * happen with mIO as container.
    */
   BluetoothSocket* mConsumer;
 
   /**
    * Connector object used to create the connection we are currently using.
    */
-  nsAutoPtr<BluetoothUnixSocketConnector> mConnector;
+  UniquePtr<BluetoothUnixSocketConnector> mConnector;
 
   /**
    * If true, do not requeue whatever task we're running
    */
   bool mShuttingDownOnIOThread;
 
   /**
    * Number of valid bytes in |mAddress|
@@ -125,17 +126,17 @@ private:
    * Task member for delayed connect task. Should only be access on consumer
    * thread.
    */
   CancelableTask* mDelayedConnectTask;
 
   /**
    * I/O buffer for received data
    */
-  nsAutoPtr<UnixSocketRawData> mBuffer;
+  UniquePtr<UnixSocketRawData> mBuffer;
 };
 
 BluetoothSocket::BluetoothSocketIO::BluetoothSocketIO(
   MessageLoop* aConsumerLoop,
   MessageLoop* aIOLoop,
   BluetoothSocket* aConsumer,
   BluetoothUnixSocketConnector* aConnector)
   : UnixSocketWatcher(aIOLoop)
@@ -390,17 +391,17 @@ BluetoothSocket::BluetoothSocketIO::Fire
 
 nsresult
 BluetoothSocket::BluetoothSocketIO::QueryReceiveBuffer(
   UnixSocketIOBuffer** aBuffer)
 {
   MOZ_ASSERT(aBuffer);
 
   if (!mBuffer) {
-    mBuffer = new UnixSocketRawData(MAX_READ_SIZE);
+    mBuffer = MakeUnique<UnixSocketRawData>(MAX_READ_SIZE);
   }
   *aBuffer = mBuffer.get();
 
   return NS_OK;
 }
 
 /**
  * |ReceiveTask| transfers data received on the I/O thread
@@ -429,24 +430,24 @@ public:
 
     BluetoothSocket* bluetoothSocket = io->GetBluetoothSocket();
     MOZ_ASSERT(bluetoothSocket);
 
     bluetoothSocket->ReceiveSocketData(mBuffer);
   }
 
 private:
-  nsAutoPtr<UnixSocketBuffer> mBuffer;
+  UniquePtr<UnixSocketBuffer> mBuffer;
 };
 
 void
 BluetoothSocket::BluetoothSocketIO::ConsumeBuffer()
 {
   GetConsumerThread()->PostTask(FROM_HERE,
-                                new ReceiveTask(this, mBuffer.forget()));
+                                new ReceiveTask(this, mBuffer.release()));
 }
 
 void
 BluetoothSocket::BluetoothSocketIO::DiscardBuffer()
 {
   // Nothing to do.
 }
 
@@ -581,67 +582,67 @@ nsresult
 BluetoothSocket::Connect(const BluetoothAddress& aDeviceAddress,
                          const BluetoothUuid& aServiceUuid,
                          BluetoothSocketType aType,
                          int aChannel,
                          bool aAuth, bool aEncrypt)
 {
   MOZ_ASSERT(!aDeviceAddress.IsCleared());
 
-  nsAutoPtr<BluetoothUnixSocketConnector> connector(
-    new BluetoothUnixSocketConnector(aDeviceAddress, aType, aChannel,
-                                     aAuth, aEncrypt));
+  UniquePtr<BluetoothUnixSocketConnector> connector =
+    MakeUnique<BluetoothUnixSocketConnector>(aDeviceAddress, aType, aChannel,
+                                             aAuth, aEncrypt);
 
-  nsresult rv = Connect(connector);
+  nsresult rv = Connect(connector.get());
   if (NS_FAILED(rv)) {
     BluetoothAddress address;
     GetAddress(address);
 
     nsAutoString addressStr;
     AddressToString(address, addressStr);
 
     BT_LOGD("%s failed. Current connected device address: %s",
            __FUNCTION__, NS_ConvertUTF16toUTF8(addressStr).get());
     return rv;
   }
-  connector.forget();
+  Unused << connector.release();
 
   return NS_OK;
 }
 
 nsresult
 BluetoothSocket::Listen(const nsAString& aServiceName,
                         const BluetoothUuid& aServiceUuid,
                         BluetoothSocketType aType,
                         int aChannel,
                         bool aAuth, bool aEncrypt)
 {
-  nsAutoPtr<BluetoothUnixSocketConnector> connector(
-    new BluetoothUnixSocketConnector(BluetoothAddress::ANY(), aType,
-                                     aChannel, aAuth, aEncrypt));
+  UniquePtr<BluetoothUnixSocketConnector> connector =
+    MakeUnique<BluetoothUnixSocketConnector>(BluetoothAddress::ANY(), aType,
+                                             aChannel, aAuth, aEncrypt);
 
-  nsresult rv = Listen(connector);
+  nsresult rv = Listen(connector.get());
   if (NS_FAILED(rv)) {
     BluetoothAddress address;
     GetAddress(address);
 
     nsAutoString addressStr;
     AddressToString(address, addressStr);
 
     BT_LOGD("%s failed. Current connected device address: %s",
            __FUNCTION__, NS_ConvertUTF16toUTF8(addressStr).get());
     return rv;
   }
-  connector.forget();
+  Unused << connector.release();
 
   return NS_OK;
 }
 
 void
-BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
+BluetoothSocket::ReceiveSocketData(UniquePtr<UnixSocketBuffer>& aBuffer)
 {
   MOZ_ASSERT(mObserver);
 
   mObserver->ReceiveSocketData(this, aBuffer);
 }
 
 bool
 BluetoothSocket::SendSocketData(const nsACString& aStr)
--- a/dom/bluetooth/bluez/BluetoothSocket.h
+++ b/dom/bluetooth/bluez/BluetoothSocket.h
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluez_BluetoothSocket_h
 #define mozilla_dom_bluetooth_bluez_BluetoothSocket_h
 
 #include "BluetoothCommon.h"
 #include "mozilla/ipc/DataSocket.h"
 #include "mozilla/ipc/UnixSocketWatcher.h"
-#include "nsAutoPtr.h"
+#include "mozilla/UniquePtr.h"
 #include "nsString.h"
 
 class MessageLoop;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothSocketObserver;
 class BluetoothUnixSocketConnector;
@@ -39,17 +39,17 @@ public:
                   bool aAuth, bool aEncrypt);
 
   /**
    * Method to be called whenever data is received. This is only called on the
    * consumer thread.
    *
    * @param aBuffer Data received from the socket.
    */
-  void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketBuffer>& aBuffer);
+  void ReceiveSocketData(UniquePtr<mozilla::ipc::UnixSocketBuffer>& aBuffer);
 
   /**
    * Convenience function for sending strings to the socket (common in bluetooth
    * profile usage). Converts to a UnixSocketRawData struct. Can only be called
    * on originating thread.
    *
    * @param aMessage String to be sent to socket
    *
--- a/dom/bluetooth/common/BluetoothCommon.h
+++ b/dom/bluetooth/common/BluetoothCommon.h
@@ -7,17 +7,16 @@
 #ifndef mozilla_dom_bluetooth_BluetoothCommon_h
 #define mozilla_dom_bluetooth_BluetoothCommon_h
 
 #include <algorithm>
 #include "mozilla/Compiler.h"
 #include "mozilla/Endian.h"
 #include "mozilla/Observer.h"
 #include "mozilla/UniquePtr.h"
-#include "nsAutoPtr.h"
 #include "nsPrintfCString.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 extern bool gBluetoothDebugFlag;
 
 #define SWITCH_BT_DEBUG(V) (gBluetoothDebugFlag = V)
 
--- a/dom/bluetooth/common/BluetoothProfileController.h
+++ b/dom/bluetooth/common/BluetoothProfileController.h
@@ -3,18 +3,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_BluetoothProfileController_h
 #define mozilla_dom_bluetooth_BluetoothProfileController_h
 
 #include "BluetoothUuidHelper.h"
+#include "nsCOMPtr.h"
 #include "nsISupportsImpl.h"
-#include "nsAutoPtr.h"
 #include "nsITimer.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 /*
  * Class of Device(CoD): 32-bit unsigned integer
  *
  *  31   24  23    13 12     8 7      2 1 0
--- a/dom/bluetooth/common/BluetoothReplyRunnable.cpp
+++ b/dom/bluetooth/common/BluetoothReplyRunnable.cpp
@@ -23,17 +23,17 @@ BluetoothReplyRunnable::BluetoothReplyRu
   : mPromise(aPromise)
   , mDOMRequest(aReq)
   , mErrorStatus(STATUS_FAIL)
 {}
 
 void
 BluetoothReplyRunnable::SetReply(BluetoothReply* aReply)
 {
-  mReply = aReply;
+  mReply.reset(aReply);
 }
 
 void
 BluetoothReplyRunnable::ReleaseMembers()
 {
   mDOMRequest = nullptr;
   mPromise = nullptr;
 }
--- a/dom/bluetooth/common/BluetoothReplyRunnable.h
+++ b/dom/bluetooth/common/BluetoothReplyRunnable.h
@@ -2,20 +2,21 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_BluetoothReplyRunnable_h
 #define mozilla_dom_bluetooth_BluetoothReplyRunnable_h
 
+#include "BluetoothCommon.h"
+#include "js/Value.h"
 #include "mozilla/Attributes.h"
-#include "BluetoothCommon.h"
+#include "mozilla/UniquePtr.h"
 #include "nsThreadUtils.h"
-#include "js/Value.h"
 
 class nsIDOMDOMRequest;
 
 namespace mozilla {
 namespace dom {
 class Promise;
 }
 }
@@ -48,17 +49,17 @@ protected:
 
   virtual bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) = 0;
 
   virtual nsresult FireErrorString();
 
   // This is an autoptr so we don't have to bring the ipdl include into the
   // header. We assume we'll only be running this once and it should die on
   // scope out of Run() anyways.
-  nsAutoPtr<BluetoothReply> mReply;
+  UniquePtr<BluetoothReply> mReply;
 
   RefPtr<Promise> mPromise;
 
 private:
   virtual void ParseErrorStatus();
 
   nsresult FireReplySuccess(JS::Handle<JS::Value> aVal);
 
--- a/dom/bluetooth/common/BluetoothRilListener.h
+++ b/dom/bluetooth/common/BluetoothRilListener.h
@@ -3,19 +3,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_BluetoothRilListener_h
 #define mozilla_dom_bluetooth_BluetoothRilListener_h
 
 #include "BluetoothCommon.h"
-
-#include "nsAutoPtr.h"
-
 #include "nsIIccService.h"
 #include "nsIMobileConnectionService.h"
 #include "nsITelephonyCallInfo.h"
 #include "nsITelephonyService.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothRilListener;
--- a/dom/bluetooth/common/BluetoothService.cpp
+++ b/dom/bluetooth/common/BluetoothService.cpp
@@ -19,16 +19,17 @@
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/unused.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/dom/ipc/BlobParent.h"
+#include "nsAutoPtr.h"
 #include "nsContentUtils.h"
 #include "nsIObserverService.h"
 #include "nsISettingsService.h"
 #include "nsISystemMessagesInternal.h"
 #include "nsITimer.h"
 #include "nsServiceManagerUtils.h"
 #include "nsXPCOM.h"
 #include "mozilla/dom/SettingChangeNotificationBinding.h"
@@ -298,17 +299,22 @@ void
 BluetoothService::UnregisterAllSignalHandlers(BluetoothSignalObserver* aHandler)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aHandler);
 
   for (auto iter = mBluetoothSignalObserverTable.Iter();
        !iter.Done();
        iter.Next()) {
+
+    // FIXME: Remove #include <nsAutoPtr.h> near the top
+    // of this file when the hash table has been converted
+    // to |UniquePtr<>|
     nsAutoPtr<BluetoothSignalObserverList>& ol = iter.Data();
+
     ol->RemoveObserver(aHandler);
     // We shouldn't have duplicate instances in the ObserverList, but there's
     // no appropriate way to do duplication check while registering, so
     // assertions are added here.
     MOZ_ASSERT(!ol->RemoveObserver(aHandler));
     if (ol->Length() == 0) {
       iter.Remove();
     }
--- a/dom/bluetooth/common/BluetoothService.h
+++ b/dom/bluetooth/common/BluetoothService.h
@@ -5,17 +5,16 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_BluetoothService_h
 #define mozilla_dom_bluetooth_BluetoothService_h
 
 #include "BluetoothCommon.h"
 #include "BluetoothInterface.h"
 #include "BluetoothProfileManagerBase.h"
-#include "nsAutoPtr.h"
 #include "nsClassHashtable.h"
 #include "nsIObserver.h"
 #include "nsTObserverArray.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace dom {
 class Blob;
--- a/dom/bluetooth/common/BluetoothSocketObserver.h
+++ b/dom/bluetooth/common/BluetoothSocketObserver.h
@@ -4,27 +4,28 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_BluetoothSocketObserver_h
 #define mozilla_dom_bluetooth_BluetoothSocketObserver_h
 
 #include "BluetoothCommon.h"
 #include "mozilla/ipc/SocketBase.h"
+#include "mozilla/UniquePtr.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothSocket;
 
 class BluetoothSocketObserver
 {
 public:
   virtual void ReceiveSocketData(
     BluetoothSocket* aSocket,
-    nsAutoPtr<mozilla::ipc::UnixSocketBuffer>& aBuffer) = 0;
+    UniquePtr<mozilla::ipc::UnixSocketBuffer>& aBuffer) = 0;
 
    /**
     * A callback function which would be called when a socket connection
     * is established successfully. To be more specific, this would be called
     * when socket state changes from CONNECTING/LISTENING to CONNECTED.
     */
   virtual void OnSocketConnectSuccess(BluetoothSocket* aSocket) = 0;
 
@@ -40,16 +41,16 @@ public:
     * changes from CONNECTED/LISTENING to DISCONNECTED.
     */
   virtual void OnSocketDisconnect(BluetoothSocket* aSocket) = 0;
 };
 
 #define BT_DECL_SOCKET_OBSERVER                                             \
 public:                                                                     \
   virtual void ReceiveSocketData(BluetoothSocket* aSocket,                  \
-    nsAutoPtr<mozilla::ipc::UnixSocketBuffer>& aMessage) override;          \
+    UniquePtr<mozilla::ipc::UnixSocketBuffer>& aMessage) override;          \
   virtual void OnSocketConnectSuccess(BluetoothSocket* aSocket) override;   \
   virtual void OnSocketConnectError(BluetoothSocket* aSocket) override;     \
   virtual void OnSocketDisconnect(BluetoothSocket* aSocket) override;
 
 END_BLUETOOTH_NAMESPACE
 
 #endif // mozilla_dom_bluetooth_BluetoothSocketObserver_h
--- a/dom/bluetooth/common/ObexBase.h
+++ b/dom/bluetooth/common/ObexBase.h
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_ObexBase_h
 #define mozilla_dom_bluetooth_ObexBase_h
 
 #include "BluetoothCommon.h"
 #include "mozilla/Endian.h"
-#include "nsAutoPtr.h"
+#include "mozilla/UniquePtr.h"
 #include "nsTArray.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 const char FINAL_BIT = 0x80;
 
 /**
  * Section 3.2 "Response format", IrOBEX ver 1.2
@@ -310,17 +310,17 @@ public:
     // The specified parameter don't exist in 'Application Parameters' header.
     return false;
   }
 
   const ObexHeader* GetHeader(ObexHeaderId aId) const
   {
     for (int i = 0, length = mHeaders.Length(); i < length; ++i) {
       if (mHeaders[i]->mId == aId) {
-        return mHeaders[i];
+        return mHeaders[i].get();
       }
     }
 
     return nullptr;
   }
 
   bool Has(ObexHeaderId aId) const
   {
@@ -328,17 +328,17 @@ public:
   }
 
   void ClearHeaders()
   {
     mHeaders.Clear();
   }
 
 private:
-  nsTArray<nsAutoPtr<ObexHeader> > mHeaders;
+  nsTArray<UniquePtr<ObexHeader> > mHeaders;
 };
 
 int AppendHeaderName(uint8_t* aRetBuf, int aBufferSize, const uint8_t* aName,
                      int aLength);
 int AppendHeaderBody(uint8_t* aRetBuf, int aBufferSize, const uint8_t* aBody,
                      int aLength);
 int AppendHeaderTarget(uint8_t* aRetBuf, int aBufferSize, const uint8_t* aTarget,
                        int aLength);
--- a/dom/bluetooth/ipc/BluetoothChild.h
+++ b/dom/bluetooth/ipc/BluetoothChild.h
@@ -2,25 +2,22 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_ipc_BluetoothChild_h
 #define mozilla_dom_bluetooth_ipc_BluetoothChild_h
 
+#include "mozilla/Attributes.h"
 #include "mozilla/dom/bluetooth/BluetoothCommon.h"
-
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/dom/bluetooth/PBluetoothChild.h"
 #include "mozilla/dom/bluetooth/PBluetoothRequestChild.h"
 
-#include "mozilla/Attributes.h"
-#include "nsAutoPtr.h"
-
 namespace mozilla {
 namespace dom {
 namespace bluetooth {
 
 class BluetoothServiceChildProcess;
 
 } // namespace bluetooth
 } // namespace dom
--- a/dom/bluetooth/ipc/BluetoothParent.h
+++ b/dom/bluetooth/ipc/BluetoothParent.h
@@ -2,24 +2,21 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_ipc_BluetoothParent_h
 #define mozilla_dom_bluetooth_ipc_BluetoothParent_h
 
+#include "mozilla/Attributes.h"
 #include "mozilla/dom/bluetooth/BluetoothCommon.h"
-
 #include "mozilla/dom/bluetooth/PBluetoothParent.h"
 #include "mozilla/dom/bluetooth/PBluetoothRequestParent.h"
-
-#include "mozilla/Attributes.h"
 #include "mozilla/Observer.h"
-#include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 
 template <class T>
 class nsRevocableEventPtr;
 
 namespace mozilla {
 namespace dom {
--- a/dom/canvas/test/webgl-mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest.ini
@@ -60,17 +60,17 @@ support-files = captureStream_common.js
 [webgl-mochitest/test_fb_param_crash.html]
 [webgl-mochitest/test_hidden_alpha.html]
 skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in libLLVM-3.0.so)
 [webgl-mochitest/test_hidden_depth_stencil.html]
 fail-if = (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
 [webgl-mochitest/test_implicit_color_buffer_float.html]
 [webgl-mochitest/test_highp_fs.html]
 [webgl-mochitest/test_no_arr_points.html]
-skip-if = android_version == '10' || android_version == '18' #Android 2.3 and 4.3 aws only; bug 1030942
+skip-if = android_version == '18' #Android 4.3 aws only; bug 1030942
 [webgl-mochitest/test_noprog_draw.html]
 [webgl-mochitest/test_privileged_exts.html]
 [webgl-mochitest/test_renderer_strings.html]
 [webgl-mochitest/test_sab_with_webgl.html]
 [webgl-mochitest/test_texsubimage_float.html]
 [webgl-mochitest/test_uninit_data.html]
 [webgl-mochitest/test_webgl_available.html]
 #[webgl-mochitest/test_webgl_color_buffer_float.html]
--- a/dom/media/GraphDriver.cpp
+++ b/dom/media/GraphDriver.cpp
@@ -222,21 +222,24 @@ public:
 private:
   ThreadedDriver* mDriver;
 };
 
 void
 ThreadedDriver::Start()
 {
   LIFECYCLE_LOG("Starting thread for a SystemClockDriver  %p\n", mGraphImpl);
-  nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
-  // Note: mThread may be null during event->Run() if we pass to NewNamedThread!  See AudioInitTask
-  nsresult rv = NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread));
-  if (NS_SUCCEEDED(rv)) {
-    mThread->Dispatch(event, NS_DISPATCH_NORMAL);
+  NS_WARN_IF(!mThread);
+  if (!mThread) { // Ensure we haven't already started it
+    nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
+    // Note: mThread may be null during event->Run() if we pass to NewNamedThread!  See AudioInitTask
+    nsresult rv = NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread));
+    if (NS_SUCCEEDED(rv)) {
+      mThread->Dispatch(event, NS_DISPATCH_NORMAL);
+    }
   }
 }
 
 void
 ThreadedDriver::Resume()
 {
   Start();
 }
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -321,17 +321,17 @@ class MediaRecorder::Session: public nsI
   public:
     explicit DestroyRunnable(Session* aSession)
       : mSession(aSession) {}
 
     NS_IMETHODIMP Run()
     {
       LOG(LogLevel::Debug, ("Session.DestroyRunnable session refcnt = (%d) stopIssued %d s=(%p)",
                          (int)mSession->mRefCnt, mSession->mStopIssued, mSession.get()));
-      MOZ_ASSERT(NS_IsMainThread() && mSession.get());
+      MOZ_ASSERT(NS_IsMainThread() && mSession);
       RefPtr<MediaRecorder> recorder = mSession->mRecorder;
       if (!recorder) {
         return NS_OK;
       }
       // SourceMediaStream is ended, and send out TRACK_EVENT_END notification.
       // Read Thread will be terminate soon.
       // We need to switch MediaRecorder to "Stop" state first to make sure
       // MediaRecorder is not associated with this Session anymore, then, it's
@@ -407,26 +407,32 @@ public:
 
   nsresult Pause()
   {
     LOG(LogLevel::Debug, ("Session.Pause"));
     MOZ_ASSERT(NS_IsMainThread());
 
     NS_ENSURE_TRUE(mTrackUnionStream, NS_ERROR_FAILURE);
     mTrackUnionStream->Suspend();
+    if (mEncoder) {
+      mEncoder->Suspend();
+    }
 
     return NS_OK;
   }
 
   nsresult Resume()
   {
     LOG(LogLevel::Debug, ("Session.Resume"));
     MOZ_ASSERT(NS_IsMainThread());
 
     NS_ENSURE_TRUE(mTrackUnionStream, NS_ERROR_FAILURE);
+    if (mEncoder) {
+      mEncoder->Resume();
+    }
     mTrackUnionStream->Resume();
 
     return NS_OK;
   }
 
   nsresult RequestData()
   {
     LOG(LogLevel::Debug, ("Session.RequestData"));
@@ -630,16 +636,26 @@ private:
     // The Session::stop would clean the mTrackUnionStream. If the AfterTracksAdded
     // comes after stop command, this function would crash.
     if (!mTrackUnionStream) {
       LOG(LogLevel::Debug, ("Session.InitEncoder !mTrackUnionStream %p", this));
       DoSessionEndTask(NS_OK);
       return;
     }
     mTrackUnionStream->AddListener(mEncoder);
+    // Try to use direct listeners if possible
+    DOMMediaStream* domStream = mRecorder->Stream();
+    if (domStream) {
+      mInputStream = domStream->GetInputStream()->AsSourceStream();
+      if (mInputStream) {
+        mInputStream->AddDirectListener(mEncoder);
+        mEncoder->SetDirectConnect(true);
+      }
+    }
+
     // Create a thread to read encode media data from MediaEncoder.
     if (!mReadThread) {
       nsresult rv = NS_NewNamedThread("Media_Encoder", getter_AddRefs(mReadThread));
       if (NS_FAILED(rv)) {
         LOG(LogLevel::Debug, ("Session.InitEncoder !mReadThread %p", this));
         DoSessionEndTask(rv);
         return;
       }
@@ -682,22 +698,31 @@ private:
     }
     if (NS_FAILED(NS_DispatchToMainThread(new DestroyRunnable(this)))) {
       MOZ_ASSERT(false, "NS_DispatchToMainThread DestroyRunnable failed");
     }
     mNeedSessionEndTask = false;
   }
   void CleanupStreams()
   {
-    if (mInputPort.get()) {
+    if (mInputStream) {
+      if (mEncoder) {
+        mInputStream->RemoveDirectListener(mEncoder);
+      }
+      mInputStream = nullptr;
+    }
+    if (mInputPort) {
       mInputPort->Destroy();
       mInputPort = nullptr;
     }
 
-    if (mTrackUnionStream.get()) {
+    if (mTrackUnionStream) {
+      if (mEncoder) {
+        mTrackUnionStream->RemoveListener(mEncoder);
+      }
       mTrackUnionStream->Destroy();
       mTrackUnionStream = nullptr;
     }
   }
 
   NS_IMETHODIMP Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) override
   {
     MOZ_ASSERT(NS_IsMainThread());
@@ -729,16 +754,17 @@ private:
 private:
   // Hold reference to MediaRecoder that ensure MediaRecorder is alive
   // if there is an active session. Access ONLY on main thread.
   RefPtr<MediaRecorder> mRecorder;
 
   // Receive track data from source and dispatch to Encoder.
   // Pause/ Resume controller.
   RefPtr<ProcessedMediaStream> mTrackUnionStream;
+  RefPtr<SourceMediaStream> mInputStream;
   RefPtr<MediaInputPort> mInputPort;
 
   // Runnable thread for read data from MediaEncode.
   nsCOMPtr<nsIThread> mReadThread;
   // MediaEncoder pipeline.
   RefPtr<MediaEncoder> mEncoder;
   // A buffer to cache encoded meda data.
   nsAutoPtr<EncodedBufferCache> mEncodedBufferCache;
--- a/dom/media/encoder/MediaEncoder.cpp
+++ b/dom/media/encoder/MediaEncoder.cpp
@@ -4,16 +4,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "MediaEncoder.h"
 #include "MediaDecoder.h"
 #include "nsIPrincipal.h"
 #include "nsMimeTypes.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPtr.h"
+#include "mozilla/gfx/Point.h" // IntSize
 
 #include"GeckoProfiler.h"
 #include "OggWriter.h"
 #include "OpusTrackEncoder.h"
 
 #ifdef MOZ_VORBIS
 #include "VorbisTrackEncoder.h"
 #endif
@@ -32,35 +33,83 @@
 #endif
 
 mozilla::LazyLogModule gMediaEncoderLog("MediaEncoder");
 #define LOG(type, msg) MOZ_LOG(gMediaEncoderLog, type, msg)
 
 namespace mozilla {
 
 void
+MediaEncoder::SetDirectConnect(bool aConnected)
+{
+  mDirectConnected = aConnected;
+}
+
+void
+MediaEncoder::NotifyRealtimeData(MediaStreamGraph* aGraph,
+                                 TrackID aID,
+                                 StreamTime aTrackOffset,
+                                 uint32_t aTrackEvents,
+                                 const MediaSegment& aRealtimeMedia)
+{
+  if (mSuspended == RECORD_NOT_SUSPENDED) {
+    // Process the incoming raw track data from MediaStreamGraph, called on the
+    // thread of MediaStreamGraph.
+    if (mAudioEncoder && aRealtimeMedia.GetType() == MediaSegment::AUDIO) {
+      mAudioEncoder->NotifyQueuedTrackChanges(aGraph, aID,
+                                              aTrackOffset, aTrackEvents,
+                                              aRealtimeMedia);
+
+    } else if (mVideoEncoder && aRealtimeMedia.GetType() == MediaSegment::VIDEO) {
+      mVideoEncoder->NotifyQueuedTrackChanges(aGraph, aID,
+                                              aTrackOffset, aTrackEvents,
+                                              aRealtimeMedia);
+    }
+  }
+}
+
+void
 MediaEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
                                        TrackID aID,
                                        StreamTime aTrackOffset,
                                        uint32_t aTrackEvents,
                                        const MediaSegment& aQueuedMedia,
                                        MediaStream* aInputStream,
                                        TrackID aInputTrackID)
 {
-  // Process the incoming raw track data from MediaStreamGraph, called on the
-  // thread of MediaStreamGraph.
-  if (mAudioEncoder && aQueuedMedia.GetType() == MediaSegment::AUDIO) {
-    mAudioEncoder->NotifyQueuedTrackChanges(aGraph, aID,
-                                            aTrackOffset, aTrackEvents,
-                                            aQueuedMedia);
-
-  } else if (mVideoEncoder && aQueuedMedia.GetType() == MediaSegment::VIDEO) {
-      mVideoEncoder->NotifyQueuedTrackChanges(aGraph, aID,
-                                              aTrackOffset, aTrackEvents,
-                                              aQueuedMedia);
+  if (!mDirectConnected) {
+    NotifyRealtimeData(aGraph, aID, aTrackOffset, aTrackEvents, aQueuedMedia);
+  } else {
+    if (aTrackEvents != 0) {
+      // forward events (TRACK_EVENT_ENDED) but not the media
+      if (aQueuedMedia.GetType() == MediaSegment::VIDEO) {
+        VideoSegment segment;
+        NotifyRealtimeData(aGraph, aID, aTrackOffset, aTrackEvents, segment);
+      } else {
+        AudioSegment segment;
+        NotifyRealtimeData(aGraph, aID, aTrackOffset, aTrackEvents, segment);
+      }
+    }
+    if (mSuspended == RECORD_RESUMED) {
+      if (mVideoEncoder) {
+        if (aQueuedMedia.GetType() == MediaSegment::VIDEO) {
+          // insert a null frame of duration equal to the first segment passed
+          // after Resume(), so it'll get added to one of the DirectListener frames
+          VideoSegment segment;
+          gfx::IntSize size(0,0);
+          segment.AppendFrame(nullptr, aQueuedMedia.GetDuration(), size);
+          mVideoEncoder->NotifyQueuedTrackChanges(aGraph, aID,
+                                                  aTrackOffset, aTrackEvents,
+                                                  segment);
+          mSuspended = RECORD_NOT_SUSPENDED;
+        }
+      } else {
+        mSuspended = RECORD_NOT_SUSPENDED; // no video
+      }
+    }
   }
 }
 
 void
 MediaEncoder::NotifyEvent(MediaStreamGraph* aGraph,
                           MediaStreamListener::MediaStreamGraphEvent event)
 {
   // In case that MediaEncoder does not receive a TRACK_EVENT_ENDED event.
--- a/dom/media/encoder/MediaEncoder.h
+++ b/dom/media/encoder/MediaEncoder.h
@@ -7,16 +7,17 @@
 #define MediaEncoder_h_
 
 #include "mozilla/DebugOnly.h"
 #include "TrackEncoder.h"
 #include "ContainerWriter.h"
 #include "MediaStreamGraph.h"
 #include "nsIMemoryReporter.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/Atomics.h"
 
 namespace mozilla {
 
 /**
  * MediaEncoder is the framework of encoding module, it controls and manages
  * procedures between ContainerWriter and TrackEncoder. ContainerWriter packs
  * the encoded track data with a specific container (e.g. ogg, mp4).
  * AudioTrackEncoder and VideoTrackEncoder are subclasses of TrackEncoder, and
@@ -44,17 +45,17 @@ namespace mozilla {
  * 2) Dispatch the task GetEncodedData() to a worker thread.
  *
  * 3) To start encoding, add this component to its source stream.
  *    => sourceStream->AddListener(encoder);
  *
  * 4) To stop encoding, remove this component from its source stream.
  *    => sourceStream->RemoveListener(encoder);
  */
-class MediaEncoder : public MediaStreamListener
+class MediaEncoder : public MediaStreamDirectListener
 {
 public :
   enum {
     ENCODE_METADDATA,
     ENCODE_TRACK,
     ENCODE_DONE,
     ENCODE_ERROR,
   };
@@ -69,20 +70,59 @@ public :
     : mWriter(aWriter)
     , mAudioEncoder(aAudioEncoder)
     , mVideoEncoder(aVideoEncoder)
     , mStartTime(TimeStamp::Now())
     , mMIMEType(aMIMEType)
     , mSizeOfBuffer(0)
     , mState(MediaEncoder::ENCODE_METADDATA)
     , mShutdown(false)
-  {}
+    , mDirectConnected(false)
+    , mSuspended(false)
+{}
 
   ~MediaEncoder() {};
 
+  enum SuspendState {
+    RECORD_NOT_SUSPENDED,
+    RECORD_SUSPENDED,
+    RECORD_RESUMED
+  };
+
+  /* Note - called from control code, not on MSG threads. */
+  void Suspend()
+  {
+    mSuspended = RECORD_SUSPENDED;
+  }
+
+  /**
+   * Note - called from control code, not on MSG threads.
+   * Arm to collect the Duration of the next video frame and give it
+   * to the next frame, in order to avoid any possible loss of sync. */
+  void Resume()
+  {
+    if (mSuspended == RECORD_SUSPENDED) {
+      mSuspended = RECORD_RESUMED;
+    }
+  }
+
+  /**
+   * Tells us which Notify to pay attention to for media
+   */
+  void SetDirectConnect(bool aConnected);
+
+  /**
+   * Notified by the AppendToTrack in MediaStreamGraph; aRealtimeMedia is the raw
+   * track data in form of MediaSegment.
+   */
+  void NotifyRealtimeData(MediaStreamGraph* aGraph, TrackID aID,
+                          StreamTime aTrackOffset,
+                          uint32_t aTrackEvents,
+                          const MediaSegment& aRealtimeMedia) override;
+
   /**
    * Notified by the control loop of MediaStreamGraph; aQueueMedia is the raw
    * track data in form of MediaSegment.
    */
   void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
                                 StreamTime aTrackOffset,
                                 uint32_t aTrackEvents,
                                 const MediaSegment& aQueuedMedia,
@@ -164,16 +204,18 @@ private:
   nsAutoPtr<ContainerWriter> mWriter;
   nsAutoPtr<AudioTrackEncoder> mAudioEncoder;
   nsAutoPtr<VideoTrackEncoder> mVideoEncoder;
   TimeStamp mStartTime;
   nsString mMIMEType;
   int64_t mSizeOfBuffer;
   int mState;
   bool mShutdown;
+  bool mDirectConnected;
+  Atomic<int> mSuspended;
   // Get duration from create encoder, for logging purpose
   double GetEncodeTimeStamp()
   {
     TimeDuration decodeTime;
     decodeTime = TimeStamp::Now() - mStartTime;
     return decodeTime.ToMilliseconds();
   }
 };
--- a/dom/media/mediasink/DecodedAudioDataSink.cpp
+++ b/dom/media/mediasink/DecodedAudioDataSink.cpp
@@ -33,16 +33,17 @@ DecodedAudioDataSink::DecodedAudioDataSi
                                            dom::AudioChannel aChannel)
   : AudioSink(aAudioQueue)
   , mStartTime(aStartTime)
   , mWritten(0)
   , mLastGoodPosition(0)
   , mInfo(aInfo)
   , mChannel(aChannel)
   , mPlaying(true)
+  , mPlaybackComplete(false)
 {
 }
 
 DecodedAudioDataSink::~DecodedAudioDataSink()
 {
 }
 
 RefPtr<GenericPromise>
@@ -114,17 +115,17 @@ DecodedAudioDataSink::SetPreservesPitch(
   if (mAudioStream) {
     mAudioStream->SetPreservesPitch(aPreservesPitch);
   }
 }
 
 void
 DecodedAudioDataSink::SetPlaying(bool aPlaying)
 {
-  if (!mAudioStream || mPlaying == aPlaying) {
+  if (!mAudioStream || mPlaying == aPlaying || mPlaybackComplete) {
     return;
   }
   // pause/resume AudioStream as necessary.
   if (!aPlaying && !mAudioStream->IsPaused()) {
     mAudioStream->Pause();
   } else if (aPlaying && mAudioStream->IsPaused()) {
     mAudioStream->Resume();
   }
@@ -286,16 +287,14 @@ DecodedAudioDataSink::Ended() const
   // Return true when error encountered so AudioStream can start draining.
   return AudioQueue().IsFinished() || mErrored;
 }
 
 void
 DecodedAudioDataSink::Drained()
 {
   SINK_LOG("Drained");
-  // FIXME : In OSX, the audio backend could trigger Drained() twice, then it
-  // cause the crash because the promise had already been resolve and free.
-  // You can fix it on the bug 1246108.
+  mPlaybackComplete = true;
   mEndPromise.ResolveIfExists(true, __func__);
 }
 
 } // namespace media
 } // namespace mozilla
--- a/dom/media/mediasink/DecodedAudioDataSink.h
+++ b/dom/media/mediasink/DecodedAudioDataSink.h
@@ -96,14 +96,17 @@ private:
    * Used on the callback thread of cubeb.
    */
   // The AudioData at which AudioStream::DataSource is reading.
   RefPtr<AudioData> mCurrentData;
   // Keep track of the read positoin of mCurrentData.
   UniquePtr<AudioBufferCursor> mCursor;
   // True if there is any error in processing audio data like overflow.
   bool mErrored = false;
+
+  // Set on the callback thread of cubeb once the stream has drained.
+  Atomic<bool> mPlaybackComplete;
 };
 
 } // namespace media
 } // namespace mozilla
 
 #endif
--- a/dom/media/test/crashtests/crashtests.list
+++ b/dom/media/test/crashtests/crashtests.list
@@ -87,11 +87,11 @@ load audiocontext-double-suspend.html
 load buffer-source-duration-1.html
 load buffer-source-ended-1.html
 load buffer-source-resampling-start-1.html
 load doppler-1.html
 HTTP load media-element-source-seek-1.html
 load offline-buffer-source-ended-1.html
 load oscillator-ended-1.html
 load oscillator-ended-2.html
-skip-if(winWidget||xulRuntime.OS=="Linux") load video-replay-after-audio-end.html
+load video-replay-after-audio-end.html
 # This needs to run at the end to avoid leaking busted state into other tests.
 skip-if(B2G) load 691096-1.html # bug 852821
--- a/dom/media/webaudio/test/mochitest.ini
+++ b/dom/media/webaudio/test/mochitest.ini
@@ -44,17 +44,16 @@ support-files =
 skip-if = (toolkit == 'android' && debug) || os == 'win' # bug 1127845, bug 1138468
 [test_audioBufferSourceNodeNoStart.html]
 [test_audioBufferSourceNodeNullBuffer.html]
 [test_audioBufferSourceNodeOffset.html]
 skip-if = (toolkit == 'gonk') || (toolkit == 'android') || debug #bug 906752
 [test_audioBufferSourceNodePassThrough.html]
 [test_audioBufferSourceNodeRate.html]
 [test_AudioContext.html]
-skip-if = android_version == '10' # bug 1138462
 [test_audioContextSuspendResumeClose.html]
 skip-if = buildapp == 'mulet'
 tags=capturestream
 [test_audioDestinationNode.html]
 [test_AudioListener.html]
 [test_AudioNodeDevtoolsAPI.html]
 [test_AudioParamDevtoolsAPI.html]
 [test_audioParamExponentialRamp.html]
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -792,18 +792,17 @@ CreateJSContextForWorker(WorkerPrivate* 
   };
   JS_SetSecurityCallbacks(aRuntime, &securityCallbacks);
 
   // Set up the asm.js cache callbacks
   static const JS::AsmJSCacheOps asmJSCacheOps = {
     AsmJSCacheOpenEntryForRead,
     asmjscache::CloseEntryForRead,
     AsmJSCacheOpenEntryForWrite,
-    asmjscache::CloseEntryForWrite,
-    asmjscache::GetBuildId
+    asmjscache::CloseEntryForWrite
   };
   JS::SetAsmJSCacheOps(aRuntime, &asmJSCacheOps);
 
   JSContext* workerCx = JS_NewContext(aRuntime, 0);
   if (!workerCx) {
     NS_WARNING("Could not create new context!");
     return nullptr;
   }
--- a/ipc/hal/DaemonSocket.cpp
+++ b/ipc/hal/DaemonSocket.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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 "DaemonSocket.h"
 #include "mozilla/ipc/DaemonSocketConsumer.h"
 #include "mozilla/ipc/DaemonSocketPDU.h"
+#include "mozilla/UniquePtr.h"
 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR
 
 #ifdef CHROMIUM_LOG
 #undef CHROMIUM_LOG
 #endif
 
 #if defined(MOZ_WIDGET_GONK)
 #include <android/log.h>
@@ -57,17 +58,17 @@ public:
   bool IsShutdownOnIOThread() const override;
 
   void ShutdownOnConsumerThread() override;
   void ShutdownOnIOThread() override;
 
 private:
   DaemonSocket* mConnection;
   DaemonSocketIOConsumer* mConsumer;
-  nsAutoPtr<DaemonSocketPDU> mPDU;
+  UniquePtr<DaemonSocketPDU> mPDU;
   bool mShuttingDownOnIOThread;
 };
 
 DaemonSocketIO::DaemonSocketIO(
   MessageLoop* aConsumerLoop,
   MessageLoop* aIOLoop,
   int aFd,
   ConnectionStatus aConnectionStatus,
@@ -98,17 +99,17 @@ DaemonSocketIO::~DaemonSocketIO()
 
 nsresult
 DaemonSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer)
 {
   MOZ_ASSERT(aBuffer);
 
   if (!mPDU) {
     /* There's only one PDU for receiving. We reuse it every time. */
-    mPDU = new DaemonSocketPDU(DaemonSocketPDU::PDU_MAX_PAYLOAD_LENGTH);
+    mPDU = MakeUnique<DaemonSocketPDU>(DaemonSocketPDU::PDU_MAX_PAYLOAD_LENGTH);
   }
   *aBuffer = mPDU.get();
 
   return NS_OK;
 }
 
 void
 DaemonSocketIO::ConsumeBuffer()
--- a/js/src/asmjs/Wasm.cpp
+++ b/js/src/asmjs/Wasm.cpp
@@ -445,16 +445,44 @@ DecodeConversionOperator(FunctionDecoder
     if (!CheckType(f, actual, argType))
         return false;
 
     *type = ToExprType(to);
     return true;
 }
 
 static bool
+DecodeSelectOperator(FunctionDecoder& f, ExprType* type)
+{
+    ExprType trueType;
+    if (!DecodeExpr(f, &trueType))
+        return false;
+
+    if (trueType == ExprType::I64 && !f.checkI64Support())
+        return false;
+
+    ExprType falseType;
+    if (!DecodeExpr(f, &falseType))
+        return false;
+
+    if (!CheckType(f, falseType, trueType))
+        return false;
+
+    ExprType condType;
+    if (!DecodeExpr(f, &condType))
+        return false;
+
+    if (!CheckType(f, condType, ValType::I32))
+        return false;
+
+    *type = trueType;
+    return true;
+}
+
+static bool
 DecodeIfElse(FunctionDecoder& f, bool hasElse, ExprType* type)
 {
     ExprType condType;
     if (!DecodeExpr(f, &condType))
         return false;
 
     if (!CheckType(f, condType, ValType::I32))
         return false;
@@ -638,16 +666,18 @@ DecodeExpr(FunctionDecoder& f, ExprType*
       case Expr::F32Const:
         return DecodeConstF32(f, type);
       case Expr::F64Const:
         return DecodeConstF64(f, type);
       case Expr::GetLocal:
         return DecodeGetLocal(f, type);
       case Expr::SetLocal:
         return DecodeSetLocal(f, type);
+      case Expr::Select:
+        return DecodeSelectOperator(f, type);
       case Expr::Block:
         return DecodeBlock(f, /* isLoop */ false, type);
       case Expr::Loop:
         return DecodeBlock(f, /* isLoop */ true, type);
       case Expr::If:
         return DecodeIfElse(f, /* hasElse */ false, type);
       case Expr::IfElse:
         return DecodeIfElse(f, /* hasElse */ true, type);
--- a/js/src/asmjs/WasmBinaryToText.cpp
+++ b/js/src/asmjs/WasmBinaryToText.cpp
@@ -427,37 +427,40 @@ RenderLoop(WasmRenderContext& c)
 }
 
 static bool
 RenderUnaryOperator(WasmRenderContext& c, Expr expr, ValType argType)
 {
     if (!c.buffer.append("("))
       return false;
 
+    bool success = false;
     switch (expr) {
-      case Expr::I32Clz:     c.buffer.append("i32.clz"); break;
-      case Expr::I32Ctz:     c.buffer.append("i32.ctz"); break;
-      case Expr::I32Popcnt:  c.buffer.append("i32.popcnt"); break;
-      case Expr::I64Clz:     c.buffer.append("i64.clz"); break;
-      case Expr::I64Ctz:     c.buffer.append("i64.ctz"); break;
-      case Expr::I64Popcnt:  c.buffer.append("i64.popcnt"); break;
-      case Expr::F32Abs:     c.buffer.append("f32.abs"); break;
-      case Expr::F32Neg:     c.buffer.append("f32.neg"); break;
-      case Expr::F32Ceil:    c.buffer.append("f32.ceil"); break;
-      case Expr::F32Floor:   c.buffer.append("f32.floor"); break;
-      case Expr::F32Sqrt:    c.buffer.append("f32.sqrt"); break;
-      case Expr::F32Trunc:   c.buffer.append("f32.trunc"); break;
-      case Expr::F32Nearest: c.buffer.append("f32.nearest"); break;
-      case Expr::F64Abs:     c.buffer.append("f64.abs"); break;
-      case Expr::F64Neg:     c.buffer.append("f64.neg"); break;
-      case Expr::F64Ceil:    c.buffer.append("f64.ceil"); break;
-      case Expr::F64Floor:   c.buffer.append("f64.floor"); break;
-      case Expr::F64Sqrt:    c.buffer.append("f64.sqrt"); break;
+      case Expr::I32Clz:     success = c.buffer.append("i32.clz"); break;
+      case Expr::I32Ctz:     success = c.buffer.append("i32.ctz"); break;
+      case Expr::I32Popcnt:  success = c.buffer.append("i32.popcnt"); break;
+      case Expr::I64Clz:     success = c.buffer.append("i64.clz"); break;
+      case Expr::I64Ctz:     success = c.buffer.append("i64.ctz"); break;
+      case Expr::I64Popcnt:  success = c.buffer.append("i64.popcnt"); break;
+      case Expr::F32Abs:     success = c.buffer.append("f32.abs"); break;
+      case Expr::F32Neg:     success = c.buffer.append("f32.neg"); break;
+      case Expr::F32Ceil:    success = c.buffer.append("f32.ceil"); break;
+      case Expr::F32Floor:   success = c.buffer.append("f32.floor"); break;
+      case Expr::F32Sqrt:    success = c.buffer.append("f32.sqrt"); break;
+      case Expr::F32Trunc:   success = c.buffer.append("f32.trunc"); break;
+      case Expr::F32Nearest: success = c.buffer.append("f32.nearest"); break;
+      case Expr::F64Abs:     success = c.buffer.append("f64.abs"); break;
+      case Expr::F64Neg:     success = c.buffer.append("f64.neg"); break;
+      case Expr::F64Ceil:    success = c.buffer.append("f64.ceil"); break;
+      case Expr::F64Floor:   success = c.buffer.append("f64.floor"); break;
+      case Expr::F64Sqrt:    success = c.buffer.append("f64.sqrt"); break;
       default: return false;
     }
+    if (!success)
+        return false;
 
     if (!c.buffer.append(" "))
         return false;
 
     if (!RenderExpr(c))
         return false;
 
     if (!c.buffer.append(")"))
@@ -466,58 +469,61 @@ RenderUnaryOperator(WasmRenderContext& c
 }
 
 static bool
 RenderBinaryOperator(WasmRenderContext& c, Expr expr, ValType argType)
 {
     if (!c.buffer.append("("))
       return false;
 
+    bool success = false;
     switch (expr) {
-      case Expr::I32Add:      c.buffer.append("i32.add"); break;
-      case Expr::I32Sub:      c.buffer.append("i32.sub"); break;
-      case Expr::I32Mul:      c.buffer.append("i32.mul"); break;
-      case Expr::I32DivS:     c.buffer.append("i32.div_s"); break;
-      case Expr::I32DivU:     c.buffer.append("i32.div_u"); break;
-      case Expr::I32RemS:     c.buffer.append("i32.rem_s"); break;
-      case Expr::I32RemU:     c.buffer.append("i32.rem_u"); break;
-      case Expr::I32And:      c.buffer.append("i32.and"); break;
-      case Expr::I32Or:       c.buffer.append("i32.or"); break;
-      case Expr::I32Xor:      c.buffer.append("i32.xor"); break;
-      case Expr::I32Shl:      c.buffer.append("i32.shl"); break;
-      case Expr::I32ShrS:     c.buffer.append("i32.shr_s"); break;
-      case Expr::I32ShrU:     c.buffer.append("i32.shr_u"); break;
-      case Expr::I64Add:      c.buffer.append("i64.add"); break;
-      case Expr::I64Sub:      c.buffer.append("i64.sub"); break;
-      case Expr::I64Mul:      c.buffer.append("i64.mul"); break;
-      case Expr::I64DivS:     c.buffer.append("i64.div_s"); break;
-      case Expr::I64DivU:     c.buffer.append("i64.div_u"); break;
-      case Expr::I64RemS:     c.buffer.append("i64.rem_s"); break;
-      case Expr::I64RemU:     c.buffer.append("i64.rem_u"); break;
-      case Expr::I64And:      c.buffer.append("i64.and"); break;
-      case Expr::I64Or:       c.buffer.append("i64.or"); break;
-      case Expr::I64Xor:      c.buffer.append("i64.xor"); break;
-      case Expr::I64Shl:      c.buffer.append("i64.shl"); break;
-      case Expr::I64ShrS:     c.buffer.append("i64.shr_s"); break;
-      case Expr::I64ShrU:     c.buffer.append("i64.shr_u"); break;
-      case Expr::F32Add:      c.buffer.append("f32.add"); break;
-      case Expr::F32Sub:      c.buffer.append("f32.sub"); break;
-      case Expr::F32Mul:      c.buffer.append("f32.mul"); break;
-      case Expr::F32Div:      c.buffer.append("f32.div"); break;
-      case Expr::F32Min:      c.buffer.append("f32.min"); break;
-      case Expr::F32Max:      c.buffer.append("f32.max"); break;
-      case Expr::F32CopySign: c.buffer.append("f32.copysign"); break;
-      case Expr::F64Add:      c.buffer.append("f64.add"); break;
-      case Expr::F64Sub:      c.buffer.append("f64.sub"); break;
-      case Expr::F64Mul:      c.buffer.append("f64.mul"); break;
-      case Expr::F64Div:      c.buffer.append("f64.div"); break;
-      case Expr::F64Min:      c.buffer.append("f64.min"); break;
-      case Expr::F64Max:      c.buffer.append("f64.mix"); break;
+      case Expr::I32Add:      success = c.buffer.append("i32.add"); break;
+      case Expr::I32Sub:      success = c.buffer.append("i32.sub"); break;
+      case Expr::I32Mul:      success = c.buffer.append("i32.mul"); break;
+      case Expr::I32DivS:     success = c.buffer.append("i32.div_s"); break;
+      case Expr::I32DivU:     success = c.buffer.append("i32.div_u"); break;
+      case Expr::I32RemS:     success = c.buffer.append("i32.rem_s"); break;
+      case Expr::I32RemU:     success = c.buffer.append("i32.rem_u"); break;
+      case Expr::I32And:      success = c.buffer.append("i32.and"); break;
+      case Expr::I32Or:       success = c.buffer.append("i32.or"); break;
+      case Expr::I32Xor:      success = c.buffer.append("i32.xor"); break;
+      case Expr::I32Shl:      success = c.buffer.append("i32.shl"); break;
+      case Expr::I32ShrS:     success = c.buffer.append("i32.shr_s"); break;
+      case Expr::I32ShrU:     success = c.buffer.append("i32.shr_u"); break;
+      case Expr::I64Add:      success = c.buffer.append("i64.add"); break;
+      case Expr::I64Sub:      success = c.buffer.append("i64.sub"); break;
+      case Expr::I64Mul:      success = c.buffer.append("i64.mul"); break;
+      case Expr::I64DivS:     success = c.buffer.append("i64.div_s"); break;
+      case Expr::I64DivU:     success = c.buffer.append("i64.div_u"); break;
+      case Expr::I64RemS:     success = c.buffer.append("i64.rem_s"); break;
+      case Expr::I64RemU:     success = c.buffer.append("i64.rem_u"); break;
+      case Expr::I64And:      success = c.buffer.append("i64.and"); break;
+      case Expr::I64Or:       success = c.buffer.append("i64.or"); break;
+      case Expr::I64Xor:      success = c.buffer.append("i64.xor"); break;
+      case Expr::I64Shl:      success = c.buffer.append("i64.shl"); break;
+      case Expr::I64ShrS:     success = c.buffer.append("i64.shr_s"); break;
+      case Expr::I64ShrU:     success = c.buffer.append("i64.shr_u"); break;
+      case Expr::F32Add:      success = c.buffer.append("f32.add"); break;
+      case Expr::F32Sub:      success = c.buffer.append("f32.sub"); break;
+      case Expr::F32Mul:      success = c.buffer.append("f32.mul"); break;
+      case Expr::F32Div:      success = c.buffer.append("f32.div"); break;
+      case Expr::F32Min:      success = c.buffer.append("f32.min"); break;
+      case Expr::F32Max:      success = c.buffer.append("f32.max"); break;
+      case Expr::F32CopySign: success = c.buffer.append("f32.copysign"); break;
+      case Expr::F64Add:      success = c.buffer.append("f64.add"); break;
+      case Expr::F64Sub:      success = c.buffer.append("f64.sub"); break;
+      case Expr::F64Mul:      success = c.buffer.append("f64.mul"); break;
+      case Expr::F64Div:      success = c.buffer.append("f64.div"); break;
+      case Expr::F64Min:      success = c.buffer.append("f64.min"); break;
+      case Expr::F64Max:      success = c.buffer.append("f64.mix"); break;
       default: return false;
     }
+    if (!success)
+        return false;
     if (!c.buffer.append(" "))
         return false;
     if (!RenderExpr(c))
         return false;
     if (!c.buffer.append(" "))
         return false;
     if (!RenderExpr(c))
         return false;
@@ -527,51 +533,54 @@ RenderBinaryOperator(WasmRenderContext& 
 }
 
 static bool
 RenderComparisonOperator(WasmRenderContext& c, Expr expr, ValType argType)
 {
     if (!c.buffer.append("("))
       return false;
 
+    bool success = false;
     switch (expr) {
-      case Expr::I32Eq:  c.buffer.append("i32.eq"); break;
-      case Expr::I32Ne:  c.buffer.append("i32.ne"); break;
-      case Expr::I32LtS: c.buffer.append("i32.lt_s"); break;
-      case Expr::I32LtU: c.buffer.append("i32.lt_u"); break;
-      case Expr::I32LeS: c.buffer.append("i32.le_s"); break;
-      case Expr::I32LeU: c.buffer.append("i32.le_u"); break;
-      case Expr::I32GtS: c.buffer.append("i32.gt_s"); break;
-      case Expr::I32GtU: c.buffer.append("i32.gt_u"); break;
-      case Expr::I32GeS: c.buffer.append("i32.ge_s"); break;
-      case Expr::I32GeU: c.buffer.append("i32.ge_u"); break;
-      case Expr::I64Eq:  c.buffer.append("i64.eq"); break;
-      case Expr::I64Ne:  c.buffer.append("i64.ne"); break;
-      case Expr::I64LtS: c.buffer.append("i64.lt_s"); break;
-      case Expr::I64LtU: c.buffer.append("i64.lt_u"); break;
-      case Expr::I64LeS: c.buffer.append("i64.le_s"); break;
-      case Expr::I64LeU: c.buffer.append("i64.le_u"); break;
-      case Expr::I64GtS: c.buffer.append("i64.gt_s"); break;
-      case Expr::I64GtU: c.buffer.append("i64.gt_u"); break;
-      case Expr::I64GeS: c.buffer.append("i64.ge_s"); break;
-      case Expr::I64GeU: c.buffer.append("i64.ge_u"); break;
-      case Expr::F32Eq:  c.buffer.append("f32.eq"); break;
-      case Expr::F32Ne:  c.buffer.append("f32.ne"); break;
-      case Expr::F32Lt:  c.buffer.append("f32.lt"); break;
-      case Expr::F32Le:  c.buffer.append("f32.le"); break;
-      case Expr::F32Gt:  c.buffer.append("f32.gt"); break;
-      case Expr::F32Ge:  c.buffer.append("f32.ge"); break;
-      case Expr::F64Eq:  c.buffer.append("f64.eq"); break;
-      case Expr::F64Ne:  c.buffer.append("f64.ne"); break;
-      case Expr::F64Lt:  c.buffer.append("f64.lt"); break;
-      case Expr::F64Le:  c.buffer.append("f64.le"); break;
-      case Expr::F64Gt:  c.buffer.append("f64.gt"); break;
-      case Expr::F64Ge:  c.buffer.append("f64.ge"); break;
+      case Expr::I32Eq:  success = c.buffer.append("i32.eq"); break;
+      case Expr::I32Ne:  success = c.buffer.append("i32.ne"); break;
+      case Expr::I32LtS: success = c.buffer.append("i32.lt_s"); break;
+      case Expr::I32LtU: success = c.buffer.append("i32.lt_u"); break;
+      case Expr::I32LeS: success = c.buffer.append("i32.le_s"); break;
+      case Expr::I32LeU: success = c.buffer.append("i32.le_u"); break;
+      case Expr::I32GtS: success = c.buffer.append("i32.gt_s"); break;
+      case Expr::I32GtU: success = c.buffer.append("i32.gt_u"); break;
+      case Expr::I32GeS: success = c.buffer.append("i32.ge_s"); break;
+      case Expr::I32GeU: success = c.buffer.append("i32.ge_u"); break;
+      case Expr::I64Eq:  success = c.buffer.append("i64.eq"); break;
+      case Expr::I64Ne:  success = c.buffer.append("i64.ne"); break;
+      case Expr::I64LtS: success = c.buffer.append("i64.lt_s"); break;
+      case Expr::I64LtU: success = c.buffer.append("i64.lt_u"); break;
+      case Expr::I64LeS: success = c.buffer.append("i64.le_s"); break;
+      case Expr::I64LeU: success = c.buffer.append("i64.le_u"); break;
+      case Expr::I64GtS: success = c.buffer.append("i64.gt_s"); break;
+      case Expr::I64GtU: success = c.buffer.append("i64.gt_u"); break;
+      case Expr::I64GeS: success = c.buffer.append("i64.ge_s"); break;
+      case Expr::I64GeU: success = c.buffer.append("i64.ge_u"); break;
+      case Expr::F32Eq:  success = c.buffer.append("f32.eq"); break;
+      case Expr::F32Ne:  success = c.buffer.append("f32.ne"); break;
+      case Expr::F32Lt:  success = c.buffer.append("f32.lt"); break;
+      case Expr::F32Le:  success = c.buffer.append("f32.le"); break;
+      case Expr::F32Gt:  success = c.buffer.append("f32.gt"); break;
+      case Expr::F32Ge:  success = c.buffer.append("f32.ge"); break;
+      case Expr::F64Eq:  success = c.buffer.append("f64.eq"); break;
+      case Expr::F64Ne:  success = c.buffer.append("f64.ne"); break;
+      case Expr::F64Lt:  success = c.buffer.append("f64.lt"); break;
+      case Expr::F64Le:  success = c.buffer.append("f64.le"); break;
+      case Expr::F64Gt:  success = c.buffer.append("f64.gt"); break;
+      case Expr::F64Ge:  success = c.buffer.append("f64.ge"); break;
       default: return false;
     }
+    if (!success)
+        return false;
 
     if (!c.buffer.append(" "))
         return false;
     if (!RenderExpr(c))
         return false;
     if (!c.buffer.append(" "))
         return false;
     if (!RenderExpr(c))
@@ -582,44 +591,47 @@ RenderComparisonOperator(WasmRenderConte
 }
 
 static bool
 RenderConversionOperator(WasmRenderContext& c, Expr expr, ValType to, ValType argType)
 {
     if (!c.buffer.append("("))
       return false;
 
+    bool success = false;
     switch (expr) {
-      case Expr::I32WrapI64:        c.buffer.append("i32.warp/i64"); break;
-      case Expr::I32TruncSF32:      c.buffer.append("i32.trunc_s/f32"); break;
-      case Expr::I32TruncUF32:      c.buffer.append("i32.trunc_u/f32"); break;
-      case Expr::I32ReinterpretF32: c.buffer.append("i32.reinterpret/f32"); break;
-      case Expr::I32TruncSF64:      c.buffer.append("i32.trunc_s/f64"); break;
-      case Expr::I32TruncUF64:      c.buffer.append("i32.trunc_u/f64"); break;
-      case Expr::I64ExtendSI32:     c.buffer.append("i64.extend_s/i32"); break;
-      case Expr::I64ExtendUI32:     c.buffer.append("i64.extend_u/i32"); break;
-      case Expr::I64TruncSF32:      c.buffer.append("i64.trunc_s/f32"); break;
-      case Expr::I64TruncUF32:      c.buffer.append("i64.trunc_u/f32"); break;
-      case Expr::I64TruncSF64:      c.buffer.append("i64.trunc_s/f64"); break;
-      case Expr::I64TruncUF64:      c.buffer.append("i64.trunc_u/f64"); break;
-      case Expr::I64ReinterpretF64: c.buffer.append("i64.reinterpret/f64"); break;
-      case Expr::F32ConvertSI32:    c.buffer.append("f32.convert_s/i32"); break;
-      case Expr::F32ConvertUI32:    c.buffer.append("f32.convert_u/i32"); break;
-      case Expr::F32ReinterpretI32: c.buffer.append("f32.reinterpret/i32"); break;
-      case Expr::F32ConvertSI64:    c.buffer.append("f32.convert_s/i64"); break;
-      case Expr::F32ConvertUI64:    c.buffer.append("f32.convert_u/i64"); break;
-      case Expr::F32DemoteF64:      c.buffer.append("f32.demote/f64"); break;
-      case Expr::F64ConvertSI32:    c.buffer.append("f64.convert_s/i32"); break;
-      case Expr::F64ConvertUI32:    c.buffer.append("f64.convert_u/i32"); break;
-      case Expr::F64ConvertSI64:    c.buffer.append("f64.convert_s/i64"); break;
-      case Expr::F64ConvertUI64:    c.buffer.append("f64.convert_u/i64"); break;
-      case Expr::F64ReinterpretI64: c.buffer.append("f64.reinterpret/i64"); break;
-      case Expr::F64PromoteF32:     c.buffer.append("f64.promote/f32"); break;
+      case Expr::I32WrapI64:        success = c.buffer.append("i32.warp/i64"); break;
+      case Expr::I32TruncSF32:      success = c.buffer.append("i32.trunc_s/f32"); break;
+      case Expr::I32TruncUF32:      success = c.buffer.append("i32.trunc_u/f32"); break;
+      case Expr::I32ReinterpretF32: success = c.buffer.append("i32.reinterpret/f32"); break;
+      case Expr::I32TruncSF64:      success = c.buffer.append("i32.trunc_s/f64"); break;
+      case Expr::I32TruncUF64:      success = c.buffer.append("i32.trunc_u/f64"); break;
+      case Expr::I64ExtendSI32:     success = c.buffer.append("i64.extend_s/i32"); break;
+      case Expr::I64ExtendUI32:     success = c.buffer.append("i64.extend_u/i32"); break;
+      case Expr::I64TruncSF32:      success = c.buffer.append("i64.trunc_s/f32"); break;
+      case Expr::I64TruncUF32:      success = c.buffer.append("i64.trunc_u/f32"); break;
+      case Expr::I64TruncSF64:      success = c.buffer.append("i64.trunc_s/f64"); break;
+      case Expr::I64TruncUF64:      success = c.buffer.append("i64.trunc_u/f64"); break;
+      case Expr::I64ReinterpretF64: success = c.buffer.append("i64.reinterpret/f64"); break;
+      case Expr::F32ConvertSI32:    success = c.buffer.append("f32.convert_s/i32"); break;
+      case Expr::F32ConvertUI32:    success = c.buffer.append("f32.convert_u/i32"); break;
+      case Expr::F32ReinterpretI32: success = c.buffer.append("f32.reinterpret/i32"); break;
+      case Expr::F32ConvertSI64:    success = c.buffer.append("f32.convert_s/i64"); break;
+      case Expr::F32ConvertUI64:    success = c.buffer.append("f32.convert_u/i64"); break;
+      case Expr::F32DemoteF64:      success = c.buffer.append("f32.demote/f64"); break;
+      case Expr::F64ConvertSI32:    success = c.buffer.append("f64.convert_s/i32"); break;
+      case Expr::F64ConvertUI32:    success = c.buffer.append("f64.convert_u/i32"); break;
+      case Expr::F64ConvertSI64:    success = c.buffer.append("f64.convert_s/i64"); break;
+      case Expr::F64ConvertUI64:    success = c.buffer.append("f64.convert_u/i64"); break;
+      case Expr::F64ReinterpretI64: success = c.buffer.append("f64.reinterpret/i64"); break;
+      case Expr::F64PromoteF32:     success = c.buffer.append("f64.promote/f32"); break;
       default: return false;
     }
+    if (!success)
+        return false;
 
     if (!c.buffer.append(" "))
         return false;
 
     if (!RenderExpr(c))
         return false;
 
     if (!c.buffer.append(")"))
@@ -1137,17 +1149,18 @@ RenderSignature(WasmRenderContext& c, co
               return false;
           if (!c.buffer.append(")"))
               return false;
       }
     } else if (paramsNum > 0) {
       if (!c.buffer.append(" (param"))
           return false;
       for (uint32_t i = 0; i < paramsNum; i++) {
-          c.buffer.append(" ");
+          if (!c.buffer.append(" "))
+              return false;
           ValType arg = sig.arg(i);
           if (!RenderValType(c, arg))
               return false;
       }
       if (!c.buffer.append(")"))
           return false;
     }
     if (sig.ret() != ExprType::Void) {
--- a/js/src/asmjs/WasmIonCompile.cpp
+++ b/js/src/asmjs/WasmIonCompile.cpp
@@ -453,16 +453,25 @@ class FunctionCompiler
     {
         if (inDeadCode())
             return nullptr;
         T* ins = T::NewAsmJS(alloc(), op);
         curBlock_->add(ins);
         return ins;
     }
 
+    MDefinition* select(MDefinition* trueExpr, MDefinition* falseExpr, MDefinition* condExpr)
+    {
+        if (inDeadCode())
+            return nullptr;
+        auto* ins = MAsmSelect::New(alloc(), trueExpr, falseExpr, condExpr);
+        curBlock_->add(ins);
+        return ins;
+    }
+
     MDefinition* extendI32(MDefinition* op, bool isUnsigned)
     {
         if (inDeadCode())
             return nullptr;
         MExtendInt32ToInt64* ins = MExtendInt32ToInt64::NewAsmJS(alloc(), op, isUnsigned);
         curBlock_->add(ins);
         return ins;
     }
@@ -2180,16 +2189,35 @@ EmitMultiply(FunctionCompiler& f, ValTyp
     MDefinition* rhs;
     if (!EmitExpr(f, &rhs))
         return false;
     MIRType mirType = ToMIRType(type);
     *def = f.mul(lhs, rhs, mirType, mirType == MIRType_Int32 ? MMul::Integer : MMul::Normal);
     return true;
 }
 
+static bool
+EmitSelect(FunctionCompiler& f, MDefinition** def)
+{
+    MDefinition* trueExpr;
+    if (!EmitExpr(f, &trueExpr))
+        return false;
+
+    MDefinition* falseExpr;
+    if (!EmitExpr(f, &falseExpr))
+        return false;
+
+    MDefinition* condExpr;
+    if (!EmitExpr(f, &condExpr))
+        return false;
+
+    *def = f.select(trueExpr, falseExpr, condExpr);
+    return true;
+}
+
 typedef bool IsAdd;
 
 static bool
 EmitAddOrSub(FunctionCompiler& f, ValType type, bool isAdd, MDefinition** def)
 {
     MDefinition* lhs;
     if (!EmitExpr(f, &lhs))
         return false;
@@ -2747,16 +2775,20 @@ EmitExpr(FunctionCompiler& f, MDefinitio
         return EmitGetLocal(f, def);
       case Expr::SetLocal:
         return EmitSetLocal(f, def);
       case Expr::LoadGlobal:
         return EmitLoadGlobal(f, def);
       case Expr::StoreGlobal:
         return EmitStoreGlobal(f, def);
 
+      // Select
+      case Expr::Select:
+        return EmitSelect(f, def);
+
       // I32
       case Expr::I32Const:
         return EmitLiteral(f, ValType::I32, def);
       case Expr::I32Add:
         return EmitAddOrSub(f, ValType::I32, IsAdd(true), def);
       case Expr::I32Sub:
         return EmitAddOrSub(f, ValType::I32, IsAdd(false), def);
       case Expr::I32Mul:
@@ -3042,17 +3074,16 @@ EmitExpr(FunctionCompiler& f, MDefinitio
       case Expr::I32AtomicsLoad:
         return EmitAtomicsLoad(f, def);
       case Expr::I32AtomicsStore:
         return EmitAtomicsStore(f, def);
       case Expr::I32AtomicsBinOp:
         return EmitAtomicsBinOp(f, def);
 
       // Future opcodes
-      case Expr::Select:
       case Expr::F32CopySign:
       case Expr::F32Trunc:
       case Expr::F32Nearest:
       case Expr::F64CopySign:
       case Expr::F64Nearest:
       case Expr::F64Trunc:
       case Expr::I64ReinterpretF64:
       case Expr::F64ReinterpretI64:
--- a/js/src/asmjs/WasmSerialize.h
+++ b/js/src/asmjs/WasmSerialize.h
@@ -269,19 +269,19 @@ GetCPUID(uint32_t* cpuId)
 
 class MachineId
 {
     uint32_t cpuId_;
     JS::BuildIdCharVector buildId_;
 
   public:
     bool extractCurrentState(ExclusiveContext* cx) {
-        if (!cx->asmJSCacheOps().buildId)
+        if (!cx->buildIdOp())
             return false;
-        if (!cx->asmJSCacheOps().buildId(&buildId_))
+        if (!cx->buildIdOp()(&buildId_))
             return false;
         if (!GetCPUID(&cpuId_))
             return false;
         return true;
     }
 
     size_t serializedSize() const {
         return sizeof(uint32_t) +
--- a/js/src/asmjs/WasmStubs.cpp
+++ b/js/src/asmjs/WasmStubs.cpp
@@ -946,23 +946,27 @@ wasm::GenerateInterruptStub(MacroAssembl
     // Align the stack.
     masm.ma_and(StackPointer, StackPointer, Imm32(~(ABIStackAlignment - 1)));
 
     // Store resumePC into the reserved space.
     masm.loadWasmActivation(IntArgReg0);
     masm.loadPtr(Address(IntArgReg0, WasmActivation::offsetOfResumePC()), IntArgReg1);
     masm.storePtr(IntArgReg1, Address(s0, masm.framePushed()));
 
+# ifdef USES_O32_ABI
     // MIPS ABI requires rewserving stack for registes $a0 to $a3.
     masm.subFromStackPtr(Imm32(4 * sizeof(intptr_t)));
+# endif
 
     masm.assertStackAlignment(ABIStackAlignment);
     masm.call(SymbolicAddress::HandleExecutionInterrupt);
 
+# ifdef USES_O32_ABI
     masm.addToStackPtr(Imm32(4 * sizeof(intptr_t)));
+# endif
 
     masm.branchIfFalseBool(ReturnReg, JumpTarget::Throw);
 
     // This will restore stack to the address before the call.
     masm.moveToStackPtr(s0);
     masm.PopRegsInMask(AllRegsExceptSP);
 
     // Pop resumePC into PC. Clobber HeapReg to make the jump and restore it
--- a/js/src/asmjs/WasmTextToBinary.cpp
+++ b/js/src/asmjs/WasmTextToBinary.cpp
@@ -205,16 +205,17 @@ enum class WasmAstExprKind
     ConversionOperator,
     GetLocal,
     If,
     Load,
     Nop,
     Return,
     SetLocal,
     Store,
+    TernaryOperator,
     Trap,
     UnaryOperator,
 };
 
 class WasmAstExpr : public WasmAstNode
 {
     const WasmAstExprKind kind_;
 
@@ -703,16 +704,36 @@ class WasmAstBinaryOperator final : publ
         expr_(expr), lhs_(lhs), rhs_(rhs)
     {}
 
     Expr expr() const { return expr_; }
     WasmAstExpr* lhs() const { return lhs_; }
     WasmAstExpr* rhs() const { return rhs_; }
 };
 
+class WasmAstTernaryOperator : public WasmAstExpr
+{
+    Expr expr_;
+    WasmAstExpr* op0_;
+    WasmAstExpr* op1_;
+    WasmAstExpr* op2_;
+
+  public:
+    static const WasmAstExprKind Kind = WasmAstExprKind::TernaryOperator;
+    WasmAstTernaryOperator(Expr expr, WasmAstExpr* op0, WasmAstExpr* op1, WasmAstExpr* op2)
+      : WasmAstExpr(Kind),
+        expr_(expr), op0_(op0), op1_(op1), op2_(op2)
+    {}
+
+    Expr expr() const { return expr_; }
+    WasmAstExpr* op0() const { return op0_; }
+    WasmAstExpr* op1() const { return op1_; }
+    WasmAstExpr* op2() const { return op2_; }
+};
+
 class WasmAstComparisonOperator final : public WasmAstExpr
 {
     Expr expr_;
     WasmAstExpr* lhs_;
     WasmAstExpr* rhs_;
 
   public:
     static const WasmAstExprKind Kind = WasmAstExprKind::ComparisonOperator;
@@ -799,16 +820,17 @@ class WasmToken
         OpenParen,
         Param,
         Result,
         Return,
         Segment,
         SetLocal,
         Store,
         Table,
+        TernaryOpcode,
         Text,
         Trap,
         Type,
         UnaryOpcode,
         ValueType
     };
   private:
     Kind kind_;
@@ -875,18 +897,19 @@ class WasmToken
         u.valueType_ = valueType;
     }
     explicit WasmToken(Kind kind, Expr expr, const char16_t* begin, const char16_t* end)
       : kind_(kind),
         begin_(begin),
         end_(end)
     {
         MOZ_ASSERT(begin != end);
-        MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == ComparisonOpcode ||
-                   kind_ == ConversionOpcode || kind_ == Load || kind_ == Store);
+        MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == TernaryOpcode ||
+                   kind_ == ComparisonOpcode || kind_ == ConversionOpcode ||
+                   kind_ == Load || kind_ == Store);
         u.expr_ = expr;
     }
     explicit WasmToken(const char16_t* begin)
       : kind_(Error),
         begin_(begin),
         end_(begin)
     {}
     Kind kind() const {
@@ -924,18 +947,19 @@ class WasmToken
         MOZ_ASSERT(kind_ == Float);
         return u.floatLiteralKind_;
     }
     ValType valueType() const {
         MOZ_ASSERT(kind_ == ValueType || kind_ == Const);
         return u.valueType_;
     }
     Expr expr() const {
-        MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == ComparisonOpcode ||
-                   kind_ == ConversionOpcode || kind_ == Load || kind_ == Store);
+        MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == TernaryOpcode ||
+                   kind_ == ComparisonOpcode || kind_ == ConversionOpcode ||
+                   kind_ == Load || kind_ == Store);
         return u.expr_;
     }
 };
 
 } // end anonymous namespace
 
 static bool
 IsWasmNewLine(char16_t c)
@@ -1945,16 +1969,18 @@ WasmTokenStream::next()
       case 'r':
         if (consume(MOZ_UTF16("result")))
             return WasmToken(WasmToken::Result, begin, cur_);
         if (consume(MOZ_UTF16("return")))
             return WasmToken(WasmToken::Return, begin, cur_);
         break;
 
       case 's':
+        if (consume(MOZ_UTF16("select")))
+            return WasmToken(WasmToken::TernaryOpcode, Expr::Select, begin, cur_);
         if (consume(MOZ_UTF16("set_local")))
             return WasmToken(WasmToken::SetLocal, begin, cur_);
         if (consume(MOZ_UTF16("segment")))
             return WasmToken(WasmToken::Segment, begin, cur_);
         break;
 
       case 't':
         if (consume(MOZ_UTF16("table")))
@@ -2503,16 +2529,34 @@ ParseComparisonOperator(WasmParseContext
 
     WasmAstExpr* rhs = ParseExpr(c);
     if (!rhs)
         return nullptr;
 
     return new(c.lifo) WasmAstComparisonOperator(expr, lhs, rhs);
 }
 
+static WasmAstTernaryOperator*
+ParseTernaryOperator(WasmParseContext& c, Expr expr)
+{
+    WasmAstExpr* op0 = ParseExpr(c);
+    if (!op0)
+        return nullptr;
+
+    WasmAstExpr* op1 = ParseExpr(c);
+    if (!op1)
+        return nullptr;
+
+    WasmAstExpr* op2 = ParseExpr(c);
+    if (!op2)
+        return nullptr;
+
+    return new(c.lifo) WasmAstTernaryOperator(expr, op0, op1, op2);
+}
+
 static WasmAstConversionOperator*
 ParseConversionOperator(WasmParseContext& c, Expr expr)
 {
     WasmAstExpr* op = ParseExpr(c);
     if (!op)
         return nullptr;
 
     return new(c.lifo) WasmAstConversionOperator(expr, op);
@@ -2736,16 +2780,18 @@ ParseExprInsideParens(WasmParseContext& 
       case WasmToken::Loop:
         return ParseBlock(c, Expr::Loop);
       case WasmToken::Return:
         return ParseReturn(c);
       case WasmToken::SetLocal:
         return ParseSetLocal(c);
       case WasmToken::Store:
         return ParseStore(c, token.expr());
+      case WasmToken::TernaryOpcode:
+        return ParseTernaryOperator(c, token.expr());
       case WasmToken::UnaryOpcode:
         return ParseUnaryOperator(c, token.expr());
       default:
         c.ts.generateError(token, c.error);
         return nullptr;
     }
 }
 
@@ -3340,16 +3386,24 @@ ResolveUnaryOperator(Resolver& r, WasmAs
 static bool
 ResolveBinaryOperator(Resolver& r, WasmAstBinaryOperator& b)
 {
     return ResolveExpr(r, *b.lhs()) &&
            ResolveExpr(r, *b.rhs());
 }
 
 static bool
+ResolveTernaryOperator(Resolver& r, WasmAstTernaryOperator& b)
+{
+    return ResolveExpr(r, *b.op0()) &&
+           ResolveExpr(r, *b.op1()) &&
+           ResolveExpr(r, *b.op2());
+}
+
+static bool
 ResolveComparisonOperator(Resolver& r, WasmAstComparisonOperator& b)
 {
     return ResolveExpr(r, *b.lhs()) &&
            ResolveExpr(r, *b.rhs());
 }
 
 static bool
 ResolveConversionOperator(Resolver& r, WasmAstConversionOperator& b)
@@ -3436,16 +3490,18 @@ ResolveExpr(Resolver& r, WasmAstExpr& ex
       case WasmAstExprKind::Return:
         return ResolveReturn(r, expr.as<WasmAstReturn>());
       case WasmAstExprKind::SetLocal:
         return ResolveSetLocal(r, expr.as<WasmAstSetLocal>());
       case WasmAstExprKind::Store:
         return ResolveStore(r, expr.as<WasmAstStore>());
       case WasmAstExprKind::BranchTable:
         return ResolveBranchTable(r, expr.as<WasmAstBranchTable>());
+      case WasmAstExprKind::TernaryOperator:
+        return ResolveTernaryOperator(r, expr.as<WasmAstTernaryOperator>());
       case WasmAstExprKind::UnaryOperator:
         return ResolveUnaryOperator(r, expr.as<WasmAstUnaryOperator>());
     }
     MOZ_CRASH("Bad expr kind");
 }
 
 static bool
 ResolveFunc(Resolver& r, WasmAstFunc& func)
@@ -3656,16 +3712,25 @@ static bool
 EncodeBinaryOperator(Encoder& e, WasmAstBinaryOperator& b)
 {
     return e.writeExpr(b.expr()) &&
            EncodeExpr(e, *b.lhs()) &&
            EncodeExpr(e, *b.rhs());
 }
 
 static bool
+EncodeTernaryOperator(Encoder& e, WasmAstTernaryOperator& b)
+{
+    return e.writeExpr(b.expr()) &&
+           EncodeExpr(e, *b.op0()) &&
+           EncodeExpr(e, *b.op1()) &&
+           EncodeExpr(e, *b.op2());
+}
+
+static bool
 EncodeComparisonOperator(Encoder& e, WasmAstComparisonOperator& b)
 {
     return e.writeExpr(b.expr()) &&
            EncodeExpr(e, *b.lhs()) &&
            EncodeExpr(e, *b.rhs());
 }
 
 static bool
@@ -3767,16 +3832,18 @@ EncodeExpr(Encoder& e, WasmAstExpr& expr
       case WasmAstExprKind::Return:
         return EncodeReturn(e, expr.as<WasmAstReturn>());
       case WasmAstExprKind::SetLocal:
         return EncodeSetLocal(e, expr.as<WasmAstSetLocal>());
       case WasmAstExprKind::Store:
         return EncodeStore(e, expr.as<WasmAstStore>());
       case WasmAstExprKind::BranchTable:
         return EncodeBranchTable(e, expr.as<WasmAstBranchTable>());
+      case WasmAstExprKind::TernaryOperator:
+        return EncodeTernaryOperator(e, expr.as<WasmAstTernaryOperator>());
       case WasmAstExprKind::UnaryOperator:
         return EncodeUnaryOperator(e, expr.as<WasmAstUnaryOperator>());
     }
     MOZ_CRASH("Bad expr kind");
 }
 
 /*****************************************************************************/
 // wasm AST binary serialization
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -1078,19 +1078,17 @@ StructTypeDescr::fieldDescr(size_t index
     return fieldDescrs.getDenseElement(index).toObject().as<TypeDescr>();
 }
 
 TypeDescr&
 StructTypeDescr::maybeForwardedFieldDescr(size_t index) const
 {
     ArrayObject& fieldDescrs = *MaybeForwarded(&fieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_TYPES));
     MOZ_ASSERT(index < fieldDescrs.getDenseInitializedLength());
-    JSObject& descr =
-        *MaybeForwarded(&fieldDescrs.getDenseElement(index).toObject());
-    return descr.as<TypeDescr>();
+    return MaybeForwarded(&fieldDescrs.getDenseElement(index).toObject())->as<TypeDescr>();
 }
 
 /******************************************************************************
  * Creating the TypedObject "module"
  *
  * We create one global, `TypedObject`, which contains the following
  * members:
  *
@@ -1654,16 +1652,17 @@ OutlineTypedObject::obj_trace(JSTracer* 
 
     uint8_t* oldData = typedObj.outOfLineTypedMem();
     uint8_t* newData = oldData;
 
     // Update the data pointer if the owner moved and the owner's data is
     // inline with it. Note that an array buffer pointing to data in an inline
     // typed object will never be used as an owner for another outline typed
     // object. In such cases, the owner will be the inline typed object itself.
+    MakeAccessibleAfterMovingGC(owner);
     MOZ_ASSERT_IF(owner->is<ArrayBufferObject>(),
                   !owner->as<ArrayBufferObject>().forInlineTypedObject());
     if (owner != oldOwner &&
         (owner->is<InlineTypedObject>() ||
          owner->as<ArrayBufferObject>().hasInlineData()))
     {
         newData += reinterpret_cast<uint8_t*>(owner) - reinterpret_cast<uint8_t*>(oldOwner);
         typedObj.setData(newData);
--- a/js/src/frontend/SourceNotes.h
+++ b/js/src/frontend/SourceNotes.h
@@ -28,19 +28,16 @@ namespace js {
  *              |note-type|delta|           |1 1| ext-delta |
  *              +---------+-----+           +---+-----------+
  *
  * At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE,
  * SRC_COLSPAN, SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode.
  *
  * NB: the js_SrcNoteSpec array in BytecodeEmitter.cpp is indexed by this
  * enum, so its initializers need to match the order here.
- *
- * Don't forget to update XDR_BYTECODE_VERSION in vm/Xdr.h for all such
- * incompatible source note or other bytecode changes.
  */
 #define FOR_EACH_SRC_NOTE_TYPE(M)                                                                  \
     M(SRC_NULL,         "null",        0)  /* Terminates a note vector. */                         \
     M(SRC_IF,           "if",          0)  /* JSOP_IFEQ bytecode is from an if-then. */            \
     M(SRC_IF_ELSE,      "if-else",     1)  /* JSOP_IFEQ bytecode is from an if-then-else. */       \
     M(SRC_COND,         "cond",        1)  /* JSOP_IFEQ is from conditional ?: operator. */        \
     M(SRC_FOR,          "for",         3)  /* JSOP_NOP or JSOP_POP in for(;;) loop head. */        \
     M(SRC_WHILE,        "while",       1)  /* JSOP_GOTO to for or while loop condition from before \
--- a/js/src/gc/GCInternals.h
+++ b/js/src/gc/GCInternals.h
@@ -119,16 +119,17 @@ void
 CheckHashTablesAfterMovingGC(JSRuntime* rt);
 #endif
 
 struct MovingTracer : JS::CallbackTracer
 {
     explicit MovingTracer(JSRuntime* rt) : CallbackTracer(rt, TraceWeakMapKeysValues) {}
 
     void onObjectEdge(JSObject** objp) override;
+    void onShapeEdge(Shape** shapep) override;
     void onChild(const JS::GCCellPtr& thing) override {
         MOZ_ASSERT(!RelocationOverlay::isCellForwarded(thing.asCell()));
     }
 
 #ifdef DEBUG
     TracerKind getTracerKind() const override { return TracerKind::Moving; }
 #endif
 };
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -120,16 +120,22 @@ static_assert(int(AllocKind::OBJECT_FIRS
 
 inline bool
 IsObjectAllocKind(AllocKind kind)
 {
     return kind >= AllocKind::OBJECT_FIRST && kind <= AllocKind::OBJECT_LAST;
 }
 
 inline bool
+IsShapeAllocKind(AllocKind kind)
+{
+    return kind == AllocKind::SHAPE || kind == AllocKind::ACCESSOR_SHAPE;
+}
+
+inline bool
 IsValidAllocKind(AllocKind kind)
 {
     return kind >= AllocKind::FIRST && kind <= AllocKind::LAST;
 }
 
 inline bool IsAllocKind(AllocKind kind)
 {
     return kind >= AllocKind::FIRST && kind <= AllocKind::LIMIT;
--- a/js/src/jit-test/tests/ion/testFloat32-correctness.js
+++ b/js/src/jit-test/tests/ion/testFloat32-correctness.js
@@ -157,17 +157,17 @@ test(setupComp, comp);
 // MNot
 function setupNot() {
     f32[0] = -0;
     f32[1] = 0;
     f32[2] = 1;
     f32[3] = NaN;
     f32[4] = Infinity;
     f32[5] = 42;
-    f32[5] = -23;
+    f32[6] = -23;
 }
 function not() {
     assertEq( !f32[0], true );
     assertEq( !f32[1], true );
     assertEq( !f32[2], false );
     assertEq( !f32[3], true );
     assertEq( !f32[4], false );
     assertEq( !f32[5], false );
--- a/js/src/jit-test/tests/wasm/basic-control-flow.js
+++ b/js/src/jit-test/tests/wasm/basic-control-flow.js
@@ -410,9 +410,8 @@ assertEq(f(3), -1);
 // unreachable
 
 const UNREACHABLE = /unreachable/;
 assertErrorMessage(wasmEvalText(`(module (func (trap)) (export "" 0))`), Error, UNREACHABLE);
 assertErrorMessage(wasmEvalText(`(module (func (if (trap) (i32.const 0))) (export "" 0))`), Error, UNREACHABLE);
 assertErrorMessage(wasmEvalText(`(module (func (block (br_if 0 (trap)))) (export "" 0))`), Error, UNREACHABLE);
 assertErrorMessage(wasmEvalText(`(module (func (block (br_table 0 (trap)))) (export "" 0))`), Error, UNREACHABLE);
 assertErrorMessage(wasmEvalText(`(module (func (result i32) (i32.add (i32.const 0) (trap))) (export "" 0))`), Error, UNREACHABLE);
-
--- a/js/src/jit-test/tests/wasm/basic.js
+++ b/js/src/jit-test/tests/wasm/basic.js
@@ -432,8 +432,170 @@ var {v2i, i2i, i2v} = wasmEvalText(`(mod
     (export "i2i" 7)
     (export "i2v" 8)
 )`);
 
 wasmEvalText('(module (func $foo (nop)) (func (call $foo)))');
 wasmEvalText('(module (func (call $foo)) (func $foo (nop)))');
 wasmEvalText('(module (import $bar "a" "") (func (call_import $bar)) (func $foo (nop)))', {a:()=>{}});
 
+
+// ----------------------------------------------------------------------------
+// select
+
+assertErrorMessage(() => wasmEvalText('(module (func (select (i32.const 0) (f32.const 0) (i32.const 0))))'), TypeError, mismatchError("f32", "i32"));
+assertErrorMessage(() => wasmEvalText('(module (func (select (i32.const 0) (i32.const 0) (f32.const 0))))'), TypeError, mismatchError("f32", "i32"));
+
+(function testSideEffects() {
+
+var numT = 0;
+var numF = 0;
+
+var imports = {
+    ifTrue: () => 1 + numT++,
+    ifFalse: () => -1 + numF++,
+}
+
+// Test that side-effects are applied on both branches.
+var f = wasmEvalText(`
+(module
+ (import "ifTrue" "" (result i32))
+ (import "ifFalse" "" (result i32))
+ (func (result i32) (param i32)
+  (select
+   (call_import 0)
+   (call_import 1)
+   (get_local 0)
+  )
+ )
+ (export "" 0)
+)
+`, imports);
+
+assertEq(f(-1), numT);
+assertEq(numT, 1);
+assertEq(numF, 1);
+
+assertEq(f(0), numF - 2);
+assertEq(numT, 2);
+assertEq(numF, 2);
+
+assertEq(f(1), numT);
+assertEq(numT, 3);
+assertEq(numF, 3);
+
+assertEq(f(0), numF - 2);
+assertEq(numT, 4);
+assertEq(numF, 4);
+
+assertEq(f(0), numF - 2);
+assertEq(numT, 5);
+assertEq(numF, 5);
+
+assertEq(f(1), numT);
+assertEq(numT, 6);
+assertEq(numF, 6);
+
+})();
+
+function testSelect(type, trueVal, falseVal) {
+
+    function toJS(val) {
+        switch (val) {
+            case "infinity": return Infinity;
+            case "nan": return NaN;
+            case "-0": return -0;
+            default: return val;
+        }
+    }
+
+    var trueJS = toJS(trueVal);
+    var falseJS = toJS(falseVal);
+
+    // Always true condition
+    var alwaysTrue = wasmEvalText(`
+    (module
+     (func (result ${type}) (param i32)
+      (select
+       (${type}.const ${trueVal})
+       (${type}.const ${falseVal})
+       (i32.const 1)
+      )
+     )
+     (export "" 0)
+    )
+    `, imports);
+
+    assertEq(alwaysTrue(0), trueJS);
+    assertEq(alwaysTrue(1), trueJS);
+    assertEq(alwaysTrue(-1), trueJS);
+
+    // Always false condition
+    var alwaysFalse = wasmEvalText(`
+    (module
+     (func (result ${type}) (param i32)
+      (select
+       (${type}.const ${trueVal})
+       (${type}.const ${falseVal})
+       (i32.const 0)
+      )
+     )
+     (export "" 0)
+    )
+    `, imports);
+
+    assertEq(alwaysFalse(0), falseJS);
+    assertEq(alwaysFalse(1), falseJS);
+    assertEq(alwaysFalse(-1), falseJS);
+
+    // Variable condition
+    var f = wasmEvalText(`
+    (module
+     (func (result ${type}) (param i32)
+      (select
+       (${type}.const ${trueVal})
+       (${type}.const ${falseVal})
+       (get_local 0)
+      )
+     )
+     (export "" 0)
+    )
+    `, imports);
+
+    assertEq(f(0), falseJS);
+    assertEq(f(1), trueJS);
+    assertEq(f(-1), trueJS);
+}
+
+testSelect('i32', 13, 37);
+testSelect('i32', Math.pow(2, 31) - 1, -Math.pow(2, 31));
+
+testSelect('f32', Math.fround(13.37), Math.fround(19.89));
+testSelect('f32', 'infinity', '-0');
+testSelect('f32', 'nan', Math.pow(2, -31));
+
+testSelect('f64', 13.37, 19.89);
+testSelect('f64', 'infinity', '-0');
+testSelect('f64', 'nan', Math.pow(2, -31));
+
+if (!hasI64) {
+    assertErrorMessage(() => wasmEvalText('(module (func (select (i64.const 0) (i64.const 1) (i32.const 0))))'), TypeError, /NYI/);
+} else {
+    var f = wasmEvalText(`
+    (module
+     (func (result i32) (param i32)
+      (i64.gt_s
+       (select
+        (i64.const ${Math.pow(2, 31) + 1})
+        (i64.const ${-Math.pow(2, 31) - 1})
+        (get_local 0)
+       )
+       (i64.const ${Math.pow(2, 31)})
+      )
+     )
+     (export "" 0)
+    )
+    `, imports);
+
+    assertEq(f(0), 0);
+    assertEq(f(1), 1);
+    assertEq(f(-1), 1);
+}
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -4694,35 +4694,41 @@ LIRGenerator::updateResumeState(MInstruc
 void
 LIRGenerator::updateResumeState(MBasicBlock* block)
 {
     // As Value Numbering phase can remove edges from the entry basic block to a
     // code paths reachable from the OSR entry point, we have to add fixup
     // blocks to keep the dominator tree organized the same way. These fixup
     // blocks are flaged as unreachable, and should only exist iff the graph has
     // an OSR block.
+    //
+    // Note: RangeAnalysis can flag blocks as unreachable, but they are only
+    // removed iff GVN (including UCE) is enabled.
     MOZ_ASSERT_IF(!mir()->compilingAsmJS() && !block->unreachable(), block->entryResumePoint());
-    MOZ_ASSERT_IF(block->unreachable(), block->graph().osrBlock());
+    MOZ_ASSERT_IF(block->unreachable(), block->graph().osrBlock() ||
+                  !mir()->optimizationInfo().gvnEnabled());
     lastResumePoint_ = block->entryResumePoint();
     if (JitSpewEnabled(JitSpew_IonSnapshots) && lastResumePoint_)
         SpewResumePoint(block, nullptr, lastResumePoint_);
 }
 
 bool
 LIRGenerator::visitBlock(MBasicBlock* block)
 {
     current = block->lir();
     updateResumeState(block);
 
     definePhis();
 
     // See fixup blocks added by Value Numbering, to keep the dominator relation
     // modified by the presence of the OSR block.
-    MOZ_ASSERT_IF(block->unreachable(), *block->begin() == block->lastIns());
-    MOZ_ASSERT_IF(block->unreachable(), block->graph().osrBlock());
+    MOZ_ASSERT_IF(block->unreachable(), *block->begin() == block->lastIns() ||
+                  !mir()->optimizationInfo().gvnEnabled());
+    MOZ_ASSERT_IF(block->unreachable(), block->graph().osrBlock() ||
+                  !mir()->optimizationInfo().gvnEnabled());
     for (MInstructionIterator iter = block->begin(); *iter != block->lastIns(); iter++) {
         if (!visitInstruction(*iter))
             return false;
     }
 
     if (block->successorWithPhis()) {
         // If we have a successor with phis, lower the phi input now that we
         // are approaching the join point.
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -14478,16 +14478,59 @@ class MAsmJSCall final
         return spIncrement_;
     }
 
     bool possiblyCalls() const override {
         return true;
     }
 };
 
+class MAsmSelect
+  : public MTernaryInstruction,
+    public NoTypePolicy::Data
+{
+    MAsmSelect(MDefinition* trueExpr, MDefinition* falseExpr, MDefinition *condExpr)
+      : MTernaryInstruction(trueExpr, falseExpr, condExpr)
+    {
+        MOZ_ASSERT(condExpr->type() == MIRType_Int32);
+        MOZ_ASSERT(trueExpr->type() == falseExpr->type());
+        setResultType(trueExpr->type());
+        setMovable();
+    }
+
+  public:
+    INSTRUCTION_HEADER(AsmSelect)
+
+    static MAsmSelect* New(TempAllocator& alloc, MDefinition* trueExpr, MDefinition* falseExpr,
+                           MDefinition* condExpr)
+    {
+        return new(alloc) MAsmSelect(trueExpr, falseExpr, condExpr);
+    }
+
+    MDefinition* trueExpr() const {
+        return getOperand(0);
+    }
+    MDefinition* falseExpr() const {
+        return getOperand(1);
+    }
+    MDefinition* condExpr() const {
+        return getOperand(2);
+    }
+
+    AliasSet getAliasSet() const override {
+        return AliasSet::None();
+    }
+
+    bool congruentTo(const MDefinition* ins) const override {
+        return congruentIfOperandsEqual(ins);
+    }
+
+    ALLOW_CLONE(MAsmSelect)
+};
+
 class MUnknownValue : public MNullaryInstruction
 {
   protected:
     MUnknownValue() {
         setResultType(MIRType_Value);
     }
 
   public:
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -271,16 +271,17 @@ namespace jit {
     _(AsmJSStoreGlobalVar)                                                  \
     _(AsmJSLoadFuncPtr)                                                     \
     _(AsmJSLoadFFIFunc)                                                     \
     _(AsmJSReturn)                                                          \
     _(AsmJSParameter)                                                       \
     _(AsmJSVoidReturn)                                                      \
     _(AsmJSPassStackArg)                                                    \
     _(AsmJSCall)                                                            \
+    _(AsmSelect)                                                            \
     _(NewDerivedTypedObject)                                                \
     _(RecompileCheck)                                                       \
     _(MemoryBarrier)                                                        \
     _(AsmJSCompareExchangeHeap)                                             \
     _(AsmJSAtomicExchangeHeap)                                              \
     _(AsmJSAtomicBinopHeap)                                                 \
     _(UnknownValue)                                                         \
     _(LexicalCheck)                                                         \
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -2096,16 +2096,45 @@ CodeGeneratorARM::visitAtomicTypedArrayE
         AtomicBinopToTypedArray(this, lir->mir()->operation(), arrayType, value, mem, flagTemp);
     } else {
         BaseIndex mem(elements, ToRegister(lir->index()), ScaleFromElemWidth(width));
         AtomicBinopToTypedArray(this, lir->mir()->operation(), arrayType, value, mem, flagTemp);
     }
 }
 
 void
+CodeGeneratorARM::visitAsmSelect(LAsmSelect* ins)
+{
+    MIRType mirType = ins->mir()->type();
+
+    Register cond = ToRegister(ins->condExpr());
+    masm.ma_cmp(cond, Imm32(0));
+
+    if (mirType == MIRType_Int32) {
+        Register falseExpr = ToRegister(ins->falseExpr());
+        Register out = ToRegister(ins->output());
+        MOZ_ASSERT(ToRegister(ins->trueExpr()) == out, "true expr input is reused for output");
+        masm.ma_mov(falseExpr, out, LeaveCC, Assembler::Zero);
+        return;
+    }
+
+    FloatRegister out = ToFloatRegister(ins->output());
+    MOZ_ASSERT(ToFloatRegister(ins->trueExpr()) == out, "true expr input is reused for output");
+
+    FloatRegister falseExpr = ToFloatRegister(ins->falseExpr());
+
+    if (mirType == MIRType_Double)
+        masm.moveDouble(falseExpr, out, Assembler::Zero);
+    else if (mirType == MIRType_Float32)
+        masm.moveFloat32(falseExpr, out, Assembler::Zero);
+    else
+        MOZ_CRASH("unhandled type in visitAsmSelect!");
+}
+
+void
 CodeGeneratorARM::visitAsmJSCall(LAsmJSCall* ins)
 {
     MAsmJSCall* mir = ins->mir();
 
     if (UseHardFpABI() || mir->callee().which() != MAsmJSCall::Callee::Builtin) {
         emitAsmJSCall(ins);
         return;
     }
--- a/js/src/jit/arm/CodeGenerator-arm.h
+++ b/js/src/jit/arm/CodeGenerator-arm.h
@@ -195,16 +195,17 @@ class CodeGeneratorARM : public CodeGene
     void visitNegD(LNegD* lir);
     void visitNegF(LNegF* lir);
     void visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins);
     void visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins);
     void visitAtomicTypedArrayElementBinop(LAtomicTypedArrayElementBinop* lir);
     void visitAtomicTypedArrayElementBinopForEffect(LAtomicTypedArrayElementBinopForEffect* lir);
     void visitCompareExchangeTypedArrayElement(LCompareExchangeTypedArrayElement* lir);
     void visitAtomicExchangeTypedArrayElement(LAtomicExchangeTypedArrayElement* lir);
+    void visitAsmSelect(LAsmSelect* ins);
     void visitAsmJSCall(LAsmJSCall* ins);
     void visitAsmJSLoadHeap(LAsmJSLoadHeap* ins);
     void visitAsmJSStoreHeap(LAsmJSStoreHeap* ins);
     void visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins);
     void visitAsmJSCompareExchangeCallout(LAsmJSCompareExchangeCallout* ins);
     void visitAsmJSAtomicExchangeHeap(LAsmJSAtomicExchangeHeap* ins);
     void visitAsmJSAtomicExchangeCallout(LAsmJSAtomicExchangeCallout* ins);
     void visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap* ins);
--- a/js/src/jit/arm/Lowering-arm.cpp
+++ b/js/src/jit/arm/Lowering-arm.cpp
@@ -406,16 +406,29 @@ LIRGeneratorARM::lowerUrshD(MUrsh* mir)
     MOZ_ASSERT(lhs->type() == MIRType_Int32);
     MOZ_ASSERT(rhs->type() == MIRType_Int32);
 
     LUrshD* lir = new(alloc()) LUrshD(useRegister(lhs), useRegisterOrConstant(rhs), temp());
     define(lir, mir);
 }
 
 void
+LIRGeneratorARM::visitAsmSelect(MAsmSelect* ins)
+{
+    MOZ_ASSERT(ins->type() != MIRType_Int64);
+
+    auto* lir = new(alloc()) LAsmSelect(useRegisterAtStart(ins->trueExpr()),
+                                        useRegister(ins->falseExpr()),
+                                        useRegister(ins->condExpr())
+                                       );
+
+    defineReuseInput(lir, ins, LAsmSelect::TrueExprIndex);
+}
+
+void
 LIRGeneratorARM::visitAsmJSNeg(MAsmJSNeg* ins)
 {
     if (ins->type() == MIRType_Int32) {
         define(new(alloc()) LNegI(useRegisterAtStart(ins->input())), ins);
     } else if (ins->type() == MIRType_Float32) {
         define(new(alloc()) LNegF(useRegisterAtStart(ins->input())), ins);
     } else {
         MOZ_ASSERT(ins->type() == MIRType_Double);
--- a/js/src/jit/arm/Lowering-arm.h
+++ b/js/src/jit/arm/Lowering-arm.h
@@ -89,16 +89,17 @@ class LIRGeneratorARM : public LIRGenera
 
   public:
     void visitBox(MBox* box);
     void visitUnbox(MUnbox* unbox);
     void visitReturn(MReturn* ret);
     void lowerPhi(MPhi* phi);
     void visitGuardShape(MGuardShape* ins);
     void visitGuardObjectGroup(MGuardObjectGroup* ins);
+    void visitAsmSelect(MAsmSelect* ins);
     void visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble* ins);
     void visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins);
     void visitAsmJSLoadHeap(MAsmJSLoadHeap* ins);
     void visitAsmJSStoreHeap(MAsmJSStoreHeap* ins);
     void visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr* ins);
     void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins);
     void visitAsmJSAtomicExchangeHeap(MAsmJSAtomicExchangeHeap* ins);
     void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins);
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -998,18 +998,18 @@ class MacroAssemblerARMCompat : public M
     void storePtr(Register src, AbsoluteAddress dest);
     void storeDouble(FloatRegister src, Address addr) {
         ma_vstr(src, addr);
     }
     void storeDouble(FloatRegister src, BaseIndex addr) {
         uint32_t scale = Imm32::ShiftOf(addr.scale).value;
         ma_vstr(src, addr.base, addr.index, scale, addr.offset);
     }
-    void moveDouble(FloatRegister src, FloatRegister dest) {
-        ma_vmov(src, dest);
+    void moveDouble(FloatRegister src, FloatRegister dest, Condition cc = Always) {
+        ma_vmov(src, dest, cc);
     }
 
     void storeFloat32(FloatRegister src, const Address& addr) {
         ma_vstr(VFPRegister(src).singleOverlay(), addr);
     }
     void storeFloat32(FloatRegister src, const BaseIndex& addr) {
         uint32_t scale = Imm32::ShiftOf(addr.scale).value;
         ma_vstr(VFPRegister(src).singleOverlay(), addr.base, addr.index, scale, addr.offset);
@@ -1436,18 +1436,18 @@ class MacroAssemblerARMCompat : public M
     void ma_storeImm(Imm32 c, const Address& dest) {
         ma_mov(c, lr);
         ma_str(lr, dest);
     }
     BufferOffset ma_BoundsCheck(Register bounded) {
         return as_cmp(bounded, Imm8(0));
     }
 
-    void moveFloat32(FloatRegister src, FloatRegister dest) {
-        as_vmov(VFPRegister(dest).singleOverlay(), VFPRegister(src).singleOverlay());
+    void moveFloat32(FloatRegister src, FloatRegister dest, Condition cc = Always) {
+        as_vmov(VFPRegister(dest).singleOverlay(), VFPRegister(src).singleOverlay(), cc);
     }
 
     void loadWasmActivation(Register dest) {
         loadPtr(Address(GlobalReg, wasm::ActivationGlobalDataOffset - AsmJSGlobalRegBias), dest);
     }
     void loadAsmJSHeapRegisterFromGlobalData() {
         loadPtr(Address(GlobalReg, wasm::HeapGlobalDataOffset - AsmJSGlobalRegBias), HeapReg);
     }
--- a/js/src/jit/arm64/Lowering-arm64.cpp
+++ b/js/src/jit/arm64/Lowering-arm64.cpp
@@ -197,16 +197,22 @@ LIRGeneratorARM64::lowerUrshD(MUrsh* mir
 
 void
 LIRGeneratorARM64::visitAsmJSNeg(MAsmJSNeg* ins)
 {
     MOZ_CRASH("visitAsmJSNeg");
 }
 
 void
+LIRGeneratorARM64::visitAsmSelect(MAsmSelect* ins)
+{
+    MOZ_CRASH("visitAsmSelect");
+}
+
+void
 LIRGeneratorARM64::lowerUDiv(MDiv* div)
 {
     MOZ_CRASH("lowerUDiv");
 }
 
 void
 LIRGeneratorARM64::lowerUMod(MMod* mod)
 {
--- a/js/src/jit/arm64/Lowering-arm64.h
+++ b/js/src/jit/arm64/Lowering-arm64.h
@@ -79,16 +79,17 @@ class LIRGeneratorARM64 : public LIRGene
     void lowerModI(MMod* mod);
     void lowerDivI64(MDiv* div);
     void lowerModI64(MMod* mod);
     void lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs);
     void lowerUDiv(MDiv* div);
     void lowerUMod(MMod* mod);
     void visitPowHalf(MPowHalf* ins);
     void visitAsmJSNeg(MAsmJSNeg* ins);
+    void visitAsmSelect(MAsmSelect* ins);
 
     LTableSwitchV* newLTableSwitchV(MTableSwitch* ins);
     LTableSwitch* newLTableSwitch(const LAllocation& in,
                                   const LDefinition& inputCopy,
                                   MTableSwitch* ins);
 
   public:
     void visitBox(MBox* box);
--- a/js/src/jit/mips-shared/Architecture-mips-shared.cpp
+++ b/js/src/jit/mips-shared/Architecture-mips-shared.cpp
@@ -6,18 +6,18 @@
 
 #include "jit/mips-shared/Architecture-mips-shared.h"
 
 #include <fcntl.h>
 #include <unistd.h>
 
 #include "jit/RegisterSets.h"
 
-#define HWCAP_MIPS (1 << 31)
-#define HWCAP_LOONGSON (1 << 30)
+#define HWCAP_MIPS (1 << 28)
+#define HWCAP_LOONGSON (1 << 27)
 #define HWCAP_FPU (1 << 0)
 
 namespace js {
 namespace jit {
 
 uint32_t GetMIPSFlags()
 {
     static uint32_t flags = 0;
--- a/js/src/jit/none/Lowering-none.h
+++ b/js/src/jit/none/Lowering-none.h
@@ -80,16 +80,17 @@ class LIRGeneratorNone : public LIRGener
     void visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr* ins) { MOZ_CRASH(); }
     void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins) { MOZ_CRASH(); }
     void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins) { MOZ_CRASH(); }
     void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins) { MOZ_CRASH(); }
     void visitAtomicExchangeTypedArrayElement(MAtomicExchangeTypedArrayElement* ins) { MOZ_CRASH(); }
     void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins) { MOZ_CRASH(); }
     void visitAsmJSAtomicExchangeHeap(MAsmJSAtomicExchangeHeap* ins) { MOZ_CRASH(); }
     void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins) { MOZ_CRASH(); }
+    void visitAsmSelect(MAsmSelect*) { MOZ_CRASH(); }
 
     LTableSwitch* newLTableSwitch(LAllocation, LDefinition, MTableSwitch*) { MOZ_CRASH(); }
     LTableSwitchV* newLTableSwitchV(MTableSwitch*) { MOZ_CRASH(); }
     void visitSimdSelect(MSimdSelect* ins) { MOZ_CRASH(); }
     void visitSimdSplatX4(MSimdSplatX4* ins) { MOZ_CRASH(); }
     void visitSimdValueX4(MSimdValueX4* lir) { MOZ_CRASH(); }
     void visitSubstr(MSubstr*) { MOZ_CRASH(); }
     void visitSimdBinaryArith(js::jit::MSimdBinaryArith*) { MOZ_CRASH(); }
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -7250,16 +7250,67 @@ class LHasClass : public LInstructionHel
     const LAllocation* lhs() {
         return getOperand(0);
     }
     MHasClass* mir() const {
         return mir_->toHasClass();
     }
 };
 
+template<size_t Defs, size_t Ops>
+class LAsmSelectBase : public LInstructionHelper<Defs, Ops, 0>
+{
+    typedef LInstructionHelper<Defs, Ops, 0> Base;
+  public:
+    static const size_t TrueExprIndex = 0;
+
+    const LAllocation* trueExpr() {
+        static_assert(TrueExprIndex == 0, "trueExprIndex kept in sync");
+        return Base::getOperand(0);
+    }
+    const LAllocation* falseExpr() {
+        return Base::getOperand(1);
+    }
+    const LAllocation* condExpr() {
+        return Base::getOperand(2);
+    }
+
+    MAsmSelect* mir() const {
+        return Base::mir_->toAsmSelect();
+    }
+};
+
+class LAsmSelect : public LAsmSelectBase<1, 3>
+{
+  public:
+    LIR_HEADER(AsmSelect);
+
+    LAsmSelect(const LAllocation& trueExpr, const LAllocation& falseExpr, const LAllocation& cond) {
+        static_assert(TrueExprIndex == 0, "trueExprIndex kept in sync");
+        setOperand(0, trueExpr);
+        setOperand(1, falseExpr);
+        setOperand(2, cond);
+    }
+};
+
+class LAsmSelectI64 : public LAsmSelectBase<INT64_PIECES, 2 * INT64_PIECES + 1>
+{
+  public:
+    LIR_HEADER(AsmSelectI64);
+
+    LAsmSelectI64(const LInt64Allocation& trueExpr, const LInt64Allocation& falseExpr,
+                  const LAllocation& cond)
+    {
+        static_assert(TrueExprIndex == 0, "trueExprIndex kept in sync");
+        setInt64Operand(0, trueExpr);
+        setInt64Operand(1, falseExpr);
+        setOperand(2, cond);
+    }
+};
+
 class LAsmJSLoadHeap : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(AsmJSLoadHeap);
     explicit LAsmJSLoadHeap(const LAllocation& ptr) {
         setOperand(0, ptr);
     }
     MAsmJSLoadHeap* mir() const {
--- a/js/src/jit/shared/LOpcodes-shared.h
+++ b/js/src/jit/shared/LOpcodes-shared.h
@@ -350,16 +350,18 @@
     _(GetDOMMemberV)                \
     _(GetDOMMemberT)                \
     _(SetDOMProperty)               \
     _(CallDOMNative)                \
     _(IsCallable)                   \
     _(IsObject)                     \
     _(IsObjectAndBranch)            \
     _(HasClass)                     \
+    _(AsmSelect)                    \
+    _(AsmSelectI64)                 \
     _(AsmJSLoadHeap)                \
     _(AsmJSStoreHeap)               \
     _(AsmJSLoadFuncPtr)             \
     _(AsmJSLoadGlobalVar)           \
     _(AsmJSStoreGlobalVar)          \
     _(AsmJSLoadFFIFunc)             \
     _(AsmJSParameter)               \
     _(AsmJSReturn)                  \
--- a/js/src/jit/x64/Assembler-x64.h
+++ b/js/src/jit/x64/Assembler-x64.h
@@ -433,16 +433,32 @@ class Assembler : public AssemblerX86Sha
     }
     void vmovq(FloatRegister src, Register dest) {
         masm.vmovq_rr(src.encoding(), dest.encoding());
     }
     void movq(Register src, Register dest) {
         masm.movq_rr(src.encoding(), dest.encoding());
     }
 
+    void cmovzq(const Operand& src, Register dest) {
+        switch (src.kind()) {
+          case Operand::REG:
+            masm.cmovzq_rr(src.reg(), dest.encoding());
+            break;
+          case Operand::MEM_REG_DISP:
+            masm.cmovzq_mr(src.disp(), src.base(), dest.encoding());
+            break;
+          case Operand::MEM_SCALE:
+            masm.cmovzq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
+            break;
+          default:
+            MOZ_CRASH("unexpected operand kind");
+        }
+    }
+
     void xchgq(Register src, Register dest) {
         masm.xchgq_rr(src.encoding(), dest.encoding());
     }
 
     void movslq(Register src, Register dest) {
         masm.movslq_rr(src.encoding(), dest.encoding());
     }
     void movslq(const Operand& src, Register dest) {
--- a/js/src/jit/x64/BaseAssembler-x64.h
+++ b/js/src/jit/x64/BaseAssembler-x64.h
@@ -430,16 +430,32 @@ class BaseAssemblerX64 : public BaseAsse
     {
         spew("testq      $0x%4x, " MEM_obs, rhs, ADDR_obs(offset, base, index, scale));
         m_formatter.oneByteOp64(OP_GROUP3_EvIz, offset, base, index, scale, GROUP3_OP_TEST);
         m_formatter.immediate32(rhs);
     }
 
     // Various move ops:
 
+    void cmovzq_rr(RegisterID src, RegisterID dst)
+    {
+        spew("cmovz     %s, %s", GPReg16Name(src), GPReg32Name(dst));
+        m_formatter.twoByteOp64(OP2_CMOVZ_GvqpEvqp, src, dst);
+    }
+    void cmovzq_mr(int32_t offset, RegisterID base, RegisterID dst)
+    {
+        spew("cmovz     " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
+        m_formatter.twoByteOp64(OP2_CMOVZ_GvqpEvqp, offset, base, dst);
+    }
+    void cmovzq_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+    {
+        spew("cmovz     " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg32Name(dst));
+        m_formatter.twoByteOp64(OP2_CMOVZ_GvqpEvqp, offset, base, index, scale, dst);
+    }
+
     void xchgq_rr(RegisterID src, RegisterID dst)
     {
         spew("xchgq      %s, %s", GPReg64Name(src), GPReg64Name(dst));
         m_formatter.oneByteOp64(OP_XCHG_GvEv, src, dst);
     }
     void xchgq_rm(RegisterID src, int32_t offset, RegisterID base)
     {
         spew("xchgq      %s, " MEM_ob, GPReg64Name(src), ADDR_ob(offset, base));
--- a/js/src/jit/x64/CodeGenerator-x64.cpp
+++ b/js/src/jit/x64/CodeGenerator-x64.cpp
@@ -473,16 +473,31 @@ CodeGeneratorX64::visitUDivOrMod64(LUDiv
     // Zero extend the lhs into rdx to make (rdx:rax).
     masm.xorl(rdx, rdx);
     masm.udivq(rhs);
 
     masm.bind(&done);
 }
 
 void
+CodeGeneratorX64::visitAsmSelectI64(LAsmSelectI64* lir)
+{
+    MOZ_ASSERT(lir->mir()->type() == MIRType_Int64);
+
+    Register cond = ToRegister(lir->condExpr());
+    Operand falseExpr = ToOperand(lir->falseExpr());
+
+    Register out = ToRegister(lir->output());
+    MOZ_ASSERT(ToRegister(lir->trueExpr()) == out, "true expr is reused for input");
+
+    masm.test32(cond, cond);
+    masm.cmovzq(falseExpr, out);
+}
+
+void
 CodeGeneratorX64::visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble* lir)
 {
     masm.convertUInt32ToDouble(ToRegister(lir->input()), ToFloatRegister(lir->output()));
 }
 
 void
 CodeGeneratorX64::visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32* lir)
 {
--- a/js/src/jit/x64/CodeGenerator-x64.h
+++ b/js/src/jit/x64/CodeGenerator-x64.h
@@ -54,16 +54,17 @@ class CodeGeneratorX64 : public CodeGene
     void visitTruncateDToInt32(LTruncateDToInt32* ins);
     void visitTruncateFToInt32(LTruncateFToInt32* ins);
     void visitWrapInt64ToInt32(LWrapInt64ToInt32* lir);
     void visitExtendInt32ToInt64(LExtendInt32ToInt64* lir);
     void visitTruncateToInt64(LTruncateToInt64* lir);
     void visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir);
     void visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins);
     void visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins);
+    void visitAsmSelectI64(LAsmSelectI64* ins);
     void visitAsmJSCall(LAsmJSCall* ins);
     void visitAsmJSLoadHeap(LAsmJSLoadHeap* ins);
     void visitAsmJSStoreHeap(LAsmJSStoreHeap* ins);
     void visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins);
     void visitAsmJSAtomicExchangeHeap(LAsmJSAtomicExchangeHeap* ins);
     void visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap* ins);
     void visitAsmJSAtomicBinopHeapForEffect(LAsmJSAtomicBinopHeapForEffect* ins);
     void visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar* ins);
--- a/js/src/jit/x86-shared/Assembler-x86-shared.h
+++ b/js/src/jit/x86-shared/Assembler-x86-shared.h
@@ -440,16 +440,31 @@ class AssemblerX86Shared : public Assemb
     void nopAlign(int alignment) {
         masm.nopAlign(alignment);
     }
     void writeCodePointer(CodeOffset* label) {
         // A CodeOffset only has one use, bake in the "end of list" value.
         masm.jumpTablePointer(LabelBase::INVALID_OFFSET);
         label->bind(masm.size());
     }
+    void cmovz(const Operand& src, Register dest) {
+        switch (src.kind()) {
+          case Operand::REG:
+            masm.cmovz_rr(src.reg(), dest.encoding());
+            break;
+          case Operand::MEM_REG_DISP:
+            masm.cmovz_mr(src.disp(), src.base(), dest.encoding());
+            break;
+          case Operand::MEM_SCALE:
+            masm.cmovz_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
+            break;
+          default:
+            MOZ_CRASH("unexpected operand kind");
+        }
+    }
     void movl(Imm32 imm32, Register dest) {
         masm.movl_i32r(imm32.value, dest.encoding());
     }
     void movl(Register src, Register dest) {
         masm.movl_rr(src.encoding(), dest.encoding());
     }
     void movl(const Operand& src, Register dest) {
         switch (src.kind()) {
--- a/js/src/jit/x86-shared/BaseAssembler-x86-shared.h
+++ b/js/src/jit/x86-shared/BaseAssembler-x86-shared.h
@@ -1766,16 +1766,32 @@ public:
         m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, src);
     }
     void xchgl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
     {
         spew("xchgl      %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
         m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, index, scale, src);
     }
 
+    void cmovz_rr(RegisterID src, RegisterID dst)
+    {
+        spew("cmovz     %s, %s", GPReg16Name(src), GPReg32Name(dst));
+        m_formatter.twoByteOp(OP2_CMOVZ_GvqpEvqp, src, dst);
+    }
+    void cmovz_mr(int32_t offset, RegisterID base, RegisterID dst)
+    {
+        spew("cmovz     " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
+        m_formatter.twoByteOp(OP2_CMOVZ_GvqpEvqp, offset, base, dst);
+    }
+    void cmovz_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+    {
+        spew("cmovz     " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg32Name(dst));
+        m_formatter.twoByteOp(OP2_CMOVZ_GvqpEvqp, offset, base, index, scale, dst);
+    }
+
     void movl_rr(RegisterID src, RegisterID dst)
     {
         spew("movl       %s, %s", GPReg32Name(src), GPReg32Name(dst));
         m_formatter.oneByteOp(OP_MOV_GvEv, src, dst);
     }
 
     void movw_rm(RegisterID src, int32_t offset, RegisterID base)
     {
--- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
@@ -296,16 +296,57 @@ CodeGeneratorX86Shared::visitAsmJSPassSt
               default: break;
             }
             MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("unexpected mir type in AsmJSPassStackArg");
         }
     }
 }
 
 void
+CodeGeneratorX86Shared::visitAsmSelect(LAsmSelect* ins)
+{
+    MIRType mirType = ins->mir()->type();
+
+    Register cond = ToRegister(ins->condExpr());
+    Operand falseExpr = ToOperand(ins->falseExpr());
+
+    masm.test32(cond, cond);
+
+    if (mirType == MIRType_Int32) {
+        Register out = ToRegister(ins->output());
+        MOZ_ASSERT(ToRegister(ins->trueExpr()) == out, "true expr input is reused for output");
+        masm.cmovz(falseExpr, out);
+        return;
+    }
+
+    FloatRegister out = ToFloatRegister(ins->output());
+    MOZ_ASSERT(ToFloatRegister(ins->trueExpr()) == out, "true expr input is reused for output");
+
+    Label done;
+    masm.j(Assembler::NonZero, &done);
+
+    if (mirType == MIRType_Float32) {
+        if (falseExpr.kind() == Operand::FPREG)
+            masm.moveFloat32(ToFloatRegister(ins->falseExpr()), out);
+        else
+            masm.loadFloat32(falseExpr, out);
+    } else if (mirType == MIRType_Double) {
+        if (falseExpr.kind() == Operand::FPREG)
+            masm.moveDouble(ToFloatRegister(ins->falseExpr()), out);
+        else
+            masm.loadDouble(falseExpr, out);
+    } else {
+        MOZ_CRASH("unhandled type in visitAsmSelect!");
+    }
+
+    masm.bind(&done);
+    return;
+}
+
+void
 CodeGeneratorX86Shared::visitOutOfLineLoadTypedArrayOutOfBounds(OutOfLineLoadTypedArrayOutOfBounds* ool)
 {
     switch (ool->viewType()) {
       case Scalar::Float32x4:
       case Scalar::Int32x4:
       case Scalar::MaxTypedArrayViewType:
         MOZ_CRASH("unexpected array type");
       case Scalar::Float32:
--- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.h
+++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.h
@@ -256,16 +256,17 @@ class CodeGeneratorX86Shared : public Co
     virtual void visitRoundF(LRoundF* lir);
     virtual void visitGuardShape(LGuardShape* guard);
     virtual void visitGuardObjectGroup(LGuardObjectGroup* guard);
     virtual void visitGuardClass(LGuardClass* guard);
     virtual void visitEffectiveAddress(LEffectiveAddress* ins);
     virtual void visitUDivOrMod(LUDivOrMod* ins);
     virtual void visitUDivOrModConstant(LUDivOrModConstant *ins);
     virtual void visitAsmJSPassStackArg(LAsmJSPassStackArg* ins);
+    virtual void visitAsmSelect(LAsmSelect* ins);
     virtual void visitMemoryBarrier(LMemoryBarrier* ins);
     virtual void visitAtomicTypedArrayElementBinop(LAtomicTypedArrayElementBinop* lir);
     virtual void visitAtomicTypedArrayElementBinopForEffect(LAtomicTypedArrayElementBinopForEffect* lir);
     virtual void visitCompareExchangeTypedArrayElement(LCompareExchangeTypedArrayElement* lir);
     virtual void visitAtomicExchangeTypedArrayElement(LAtomicExchangeTypedArrayElement* lir);
 
     void visitOutOfLineLoadTypedArrayOutOfBounds(OutOfLineLoadTypedArrayOutOfBounds* ool);
     void visitOffsetBoundsCheck(OffsetBoundsCheck* oolCheck);
--- a/js/src/jit/x86-shared/Encoding-x86-shared.h
+++ b/js/src/jit/x86-shared/Encoding-x86-shared.h
@@ -141,16 +141,17 @@ enum TwoByteOpcodeID {
     OP2_MOVLHPS_VqUq    = 0x16,
     OP2_MOVSHDUP_VpsWps = 0x16,
     OP2_MOVAPD_VsdWsd   = 0x28,
     OP2_MOVAPS_VsdWsd   = 0x28,
     OP2_MOVAPS_WsdVsd   = 0x29,
     OP2_CVTSI2SD_VsdEd  = 0x2A,
     OP2_CVTTSD2SI_GdWsd = 0x2C,
     OP2_UCOMISD_VsdWsd  = 0x2E,
+    OP2_CMOVZ_GvqpEvqp  = 0x44,
     OP2_MOVMSKPD_EdVd   = 0x50,
     OP2_ANDPS_VpsWps    = 0x54,
     OP2_ANDNPS_VpsWps   = 0x55,
     OP2_ORPS_VpsWps     = 0x56,
     OP2_XORPS_VpsWps    = 0x57,
     OP2_ADDSD_VsdWsd    = 0x58,
     OP2_ADDPS_VpsWps    = 0x58,
     OP2_MULSD_VsdWsd    = 0x59,
--- a/js/src/jit/x86-shared/Lowering-x86-shared.cpp
+++ b/js/src/jit/x86-shared/Lowering-x86-shared.cpp
@@ -284,16 +284,37 @@ LIRGeneratorX86Shared::lowerModI(MMod* m
                                     useRegister(mod->rhs()),
                                     tempFixed(eax));
     if (mod->fallible())
         assignSnapshot(lir, Bailout_DoubleOutput);
     defineFixed(lir, mod, LAllocation(AnyRegister(edx)));
 }
 
 void
+LIRGeneratorX86Shared::visitAsmSelect(MAsmSelect* ins)
+{
+    if (ins->type() == MIRType_Int64) {
+        auto* lir = new(alloc()) LAsmSelectI64(useInt64RegisterAtStart(ins->trueExpr()),
+                                               useInt64(ins->falseExpr()),
+                                               useRegister(ins->condExpr())
+                                              );
+
+        defineInt64ReuseInput(lir, ins, LAsmSelectI64::TrueExprIndex);
+        return;
+    }
+
+    auto* lir = new(alloc()) LAsmSelect(useRegisterAtStart(ins->trueExpr()),
+                                        use(ins->falseExpr()),
+                                        useRegister(ins->condExpr())
+                                       );
+
+    defineReuseInput(lir, ins, LAsmSelect::TrueExprIndex);
+}
+
+void
 LIRGeneratorX86Shared::visitAsmJSNeg(MAsmJSNeg* ins)
 {
     switch (ins->type()) {
       case MIRType_Int32:
         defineReuseInput(new(alloc()) LNegI(useRegisterAtStart(ins->input())), ins, 0);
         break;
       case MIRType_Float32:
         defineReuseInput(new(alloc()) LNegF(useRegisterAtStart(ins->input())), ins, 0);
--- a/js/src/jit/x86-shared/Lowering-x86-shared.h
+++ b/js/src/jit/x86-shared/Lowering-x86-shared.h
@@ -42,16 +42,17 @@ class LIRGeneratorX86Shared : public LIR
                      MDefinition* rhs);
     void lowerForCompIx4(LSimdBinaryCompIx4* ins, MSimdBinaryComp* mir,
                          MDefinition* lhs, MDefinition* rhs);
     void lowerForCompFx4(LSimdBinaryCompFx4* ins, MSimdBinaryComp* mir,
                          MDefinition* lhs, MDefinition* rhs);
     void lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir,
                                  MDefinition* lhs, MDefinition* rhs);
     void visitAsmJSNeg(MAsmJSNeg* ins);
+    void visitAsmSelect(MAsmSelect* ins);
     void lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs);
     void lowerDivI(MDiv* div);
     void lowerModI(MMod* mod);
     void lowerUDiv(MDiv* div);
     void lowerUMod(MMod* mod);
     void lowerUrshD(MUrsh* mir);
     void lowerTruncateDToInt32(MTruncateToInt32* ins);
     void lowerTruncateFToInt32(MTruncateToInt32* ins);
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -157,19 +157,20 @@ MSG_DEF(JSMSG_UNWRAP_DENIED,           0
 // JSAPI-only (Not thrown as JS exceptions)
 MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE,  0, JSEXN_TYPEERR, "bad cloned function scope chain")
 MSG_DEF(JSMSG_CANT_CLONE_OBJECT,       0, JSEXN_TYPEERR, "can't clone object")
 MSG_DEF(JSMSG_CANT_OPEN,               2, JSEXN_ERR, "can't open {0}: {1}")
 MSG_DEF(JSMSG_USER_DEFINED_ERROR,      0, JSEXN_ERR, "JS_ReportError was called")
 
 // Internal errors
 MSG_DEF(JSMSG_ALLOC_OVERFLOW,          0, JSEXN_INTERNALERR, "allocation size overflow")
+MSG_DEF(JSMSG_BAD_BUILD_ID,            0, JSEXN_INTERNALERR, "bad build ID for XDR script")
 MSG_DEF(JSMSG_BAD_BYTECODE,            1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
-MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC,        0, JSEXN_INTERNALERR, "bad script XDR magic number")
 MSG_DEF(JSMSG_BUFFER_TOO_SMALL,        0, JSEXN_INTERNALERR, "buffer too small")
+MSG_DEF(JSMSG_BUILD_ID_NOT_AVAILABLE,  0, JSEXN_INTERNALERR, "build ID is not available")
 MSG_DEF(JSMSG_BYTECODE_TOO_BIG,        2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})")
 MSG_DEF(JSMSG_NEED_DIET,               1, JSEXN_INTERNALERR, "{0} too large")
 MSG_DEF(JSMSG_OUT_OF_MEMORY,           0, JSEXN_INTERNALERR, "out of memory")
 MSG_DEF(JSMSG_OVER_RECURSED,           0, JSEXN_INTERNALERR, "too much recursion")
 MSG_DEF(JSMSG_TOO_BIG_TO_ENCODE,       0, JSEXN_INTERNALERR, "data are to big to encode")
 MSG_DEF(JSMSG_TOO_DEEP,                1, JSEXN_INTERNALERR, "{0} nested too deeply")
 MSG_DEF(JSMSG_UNCAUGHT_EXCEPTION,      1, JSEXN_INTERNALERR, "uncaught exception: {0}")
 MSG_DEF(JSMSG_UNKNOWN_FORMAT,          1, JSEXN_INTERNALERR, "unknown bytecode format {0}")
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -7,19 +7,28 @@
 #include "jsfriendapi.h"
 #include "jsscript.h"
 #include "jsstr.h"
 
 #include "jsapi-tests/tests.h"
 
 #include "jsscriptinlines.h"
 
+static bool
+GetBuildId(JS::BuildIdCharVector* buildId)
+{
+    const char buildid[] = "testXDR";
+    return buildId->append(buildid, sizeof(buildid));
+}
+
 static JSScript*
 FreezeThaw(JSContext* cx, JS::HandleScript script)
 {
+    JS::SetBuildIdOp(cx->runtime(), GetBuildId);
+
     // freeze
     uint32_t nbytes;
     void* memory = JS_EncodeScript(cx, script, &nbytes);
     if (!memory)
         return nullptr;
 
     // thaw
     JSScript* script2 = JS_DecodeScript(cx, memory, nbytes);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6239,16 +6239,22 @@ JS_DecodeInterpretedFunction(JSContext* 
     XDRDecoder decoder(cx, data, length);
     RootedFunction funobj(cx);
     if (!decoder.codeFunction(&funobj))
         return nullptr;
     return funobj;
 }
 
 JS_PUBLIC_API(void)
+JS::SetBuildIdOp(JSRuntime* rt, JS::BuildIdOp buildIdOp)
+{
+    rt->buildIdOp = buildIdOp;
+}
+
+JS_PUBLIC_API(void)
 JS::SetAsmJSCacheOps(JSRuntime* rt, const JS::AsmJSCacheOps* ops)
 {
     rt->asmJSCacheOps = *ops;
 }
 
 char*
 JSAutoByteString::encodeLatin1(ExclusiveContext* cx, JSString* str)
 {
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5576,22 +5576,24 @@ typedef bool
 (* BuildIdOp)(BuildIdCharVector* buildId);
 
 struct AsmJSCacheOps
 {
     OpenAsmJSCacheEntryForReadOp openEntryForRead;
     CloseAsmJSCacheEntryForReadOp closeEntryForRead;
     OpenAsmJSCacheEntryForWriteOp openEntryForWrite;
     CloseAsmJSCacheEntryForWriteOp closeEntryForWrite;
-    BuildIdOp buildId;
 };
 
 extern JS_PUBLIC_API(void)
 SetAsmJSCacheOps(JSRuntime* rt, const AsmJSCacheOps* callbacks);
 
+extern JS_PUBLIC_API(void)
+SetBuildIdOp(JSRuntime* rt, BuildIdOp buildIdOp);
+
 /**
  * Convenience class for imitating a JS level for-of loop. Typical usage:
  *
  *     ForOfIterator it(cx);
  *     if (!it.init(iterable))
  *       return false;
  *     RootedValue val(cx);
  *     while (true) {
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -185,16 +185,17 @@ class ExclusiveContext : public ContextF
     }
 
     // Accessors for immutable runtime data.
     JSAtomState& names() { return *runtime_->commonNames; }
     StaticStrings& staticStrings() { return *runtime_->staticStrings; }
     bool isPermanentAtomsInitialized() { return !!runtime_->permanentAtoms; }
     FrozenAtomSet& permanentAtoms() { return *runtime_->permanentAtoms; }
     WellKnownSymbols& wellKnownSymbols() { return *runtime_->wellKnownSymbols; }
+    JS::BuildIdOp buildIdOp() { return runtime_->buildIdOp; }
     const JS::AsmJSCacheOps& asmJSCacheOps() { return runtime_->asmJSCacheOps; }
     PropertyName* emptyString() { return runtime_->emptyString; }
     FreeOp* defaultFreeOp() { return runtime_->defaultFreeOp(); }
     void* runtimeAddressForJit() { return runtime_; }
     void* runtimeAddressOfInterruptUint32() { return runtime_->addressOfInterruptUint32(); }
     void* stackLimitAddress(StackKind kind) { return &runtime_->mainThread.nativeStackLimit[kind]; }
     void* stackLimitAddressForJitCode(StackKind kind);
     uintptr_t stackLimit(StackKind kind) { return runtime_->mainThread.nativeStackLimit[kind]; }
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -960,19 +960,16 @@ StringIsArrayIndex(JSLinearString* str, 
 
 JS_FRIEND_API(void)
 SetPreserveWrapperCallback(JSRuntime* rt, PreserveWrapperCallback callback);
 
 JS_FRIEND_API(bool)
 IsObjectInContextCompartment(JSObject* obj, const JSContext* cx);
 
 /*
- * NB: these flag bits are encoded into the bytecode stream in the immediate
- * operand of JSOP_ITER, so don't change them without advancing vm/Xdr.h's
- * XDR_BYTECODE_VERSION.
  * NB: keep these in sync with the copy in builtin/SelfHostingDefines.h.
  * The first three are omitted because they shouldn't be used in new code.
  */
 #define JSITER_ENUMERATE  0x1   /* for-in compatible hidden default iterator */
 #define JSITER_FOREACH    0x2   /* get obj[key] for each property */
 #define JSITER_KEYVALUE   0x4   /* obsolete destructuring for-in wants [key, value] */
 #define JSITER_OWNONLY    0x8   /* iterate over obj's own properties only */
 #define JSITER_HIDDEN     0x10  /* also enumerate non-enumerable properties */
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2016,21 +2016,34 @@ AutoDisableCompactingGC::~AutoDisableCom
 }
 
 static bool
 CanRelocateZone(Zone* zone)
 {
     return !zone->isAtomsZone() && !zone->isSelfHostingZone();
 }
 
-static bool
-CanRelocateAllocKind(AllocKind kind)
-{
-    return IsObjectAllocKind(kind);
-}
+static const AllocKind AllocKindsToRelocate[] = {
+    AllocKind::FUNCTION,
+    AllocKind::FUNCTION_EXTENDED,
+    AllocKind::OBJECT0,
+    AllocKind::OBJECT0_BACKGROUND,
+    AllocKind::OBJECT2,
+    AllocKind::OBJECT2_BACKGROUND,
+    AllocKind::OBJECT4,
+    AllocKind::OBJECT4_BACKGROUND,
+    AllocKind::OBJECT8,
+    AllocKind::OBJECT8_BACKGROUND,
+    AllocKind::OBJECT12,
+    AllocKind::OBJECT12_BACKGROUND,
+    AllocKind::OBJECT16,
+    AllocKind::OBJECT16_BACKGROUND,
+    AllocKind::SHAPE,
+    AllocKind::ACCESSOR_SHAPE
+};
 
 Arena*
 ArenaList::removeRemainingArenas(Arena** arenap)
 {
     // This is only ever called to remove arenas that are after the cursor, so
     // we don't need to update it.
 #ifdef DEBUG
     for (Arena* arena = *arenap; arena; arena = arena->next)
@@ -2290,43 +2303,39 @@ ArenaLists::relocateArenas(Zone* zone, A
     MOZ_ASSERT(runtime_->gc.isHeapCompacting());
     MOZ_ASSERT(!runtime_->gc.isBackgroundSweeping());
 
     // Clear all the free lists.
     purge();
 
     if (ShouldRelocateAllArenas(reason)) {
         zone->prepareForCompacting();
-        for (auto i : AllAllocKinds()) {
-            if (CanRelocateAllocKind(i)) {
-                ArenaList& al = arenaLists[i];
-                Arena* allArenas = al.head();
-                al.clear();
-                relocatedListOut = al.relocateArenas(allArenas, relocatedListOut, sliceBudget, stats);
-            }
+        for (auto kind : AllocKindsToRelocate) {
+            ArenaList& al = arenaLists[kind];
+            Arena* allArenas = al.head();
+            al.clear();
+            relocatedListOut = al.relocateArenas(allArenas, relocatedListOut, sliceBudget, stats);
         }
     } else {
         size_t arenaCount = 0;
         size_t relocCount = 0;
         AllAllocKindArray<Arena**> toRelocate;
 
-        for (auto i : AllAllocKinds()) {
-            toRelocate[i] = nullptr;
-            if (CanRelocateAllocKind(i))
-                toRelocate[i] = arenaLists[i].pickArenasToRelocate(arenaCount, relocCount);
+        for (auto kind : AllocKindsToRelocate) {
+            toRelocate[kind] = arenaLists[kind].pickArenasToRelocate(arenaCount, relocCount);
         }
 
         if (!ShouldRelocateZone(arenaCount, relocCount, reason))
             return false;
 
         zone->prepareForCompacting();
-        for (auto i : AllAllocKinds()) {
-            if (toRelocate[i]) {
-                ArenaList& al = arenaLists[i];
-                Arena* arenas = al.removeRemainingArenas(toRelocate[i]);
+        for (auto kind : AllocKindsToRelocate) {
+            if (toRelocate[kind]) {
+                ArenaList& al = arenaLists[kind];
+                Arena* arenas = al.removeRemainingArenas(toRelocate[kind]);
                 relocatedListOut = al.relocateArenas(arenas, relocatedListOut, sliceBudget, stats);
             }
         }
     }
 
     return true;
 }
 
@@ -2342,36 +2351,42 @@ GCRuntime::relocateArenas(Zone* zone, JS
     jit::StopAllOffThreadCompilations(zone);
 
     if (!zone->arenas.relocateArenas(zone, relocatedListOut, reason, sliceBudget, stats))
         return false;
 
 #ifdef DEBUG
     // Check that we did as much compaction as we should have. There
     // should always be less than one arena's worth of free cells.
-    for (auto i : AllAllocKinds()) {
-        size_t thingsPerArena = Arena::thingsPerArena(i);
-        if (CanRelocateAllocKind(i)) {
-            ArenaList& al = zone->arenas.arenaLists[i];
-            size_t freeCells = 0;
-            for (Arena* arena = al.arenaAfterCursor(); arena; arena = arena->next)
-                freeCells += arena->countFreeCells();
-            MOZ_ASSERT(freeCells < thingsPerArena);
-        }
+    for (auto i : AllocKindsToRelocate) {
+        ArenaList& al = zone->arenas.arenaLists[i];
+        size_t freeCells = 0;
+        for (Arena* arena = al.arenaAfterCursor(); arena; arena = arena->next)
+            freeCells += arena->countFreeCells();
+        MOZ_ASSERT(freeCells < Arena::thingsPerArena(i));
     }
 #endif
 
     return true;
 }
 
 void
 MovingTracer::onObjectEdge(JSObject** objp)
 {
-    if (IsForwarded(*objp))
-        *objp = Forwarded(*objp);
+    JSObject* obj = *objp;
+    if (IsForwarded(obj))
+        *objp = Forwarded(obj);
+}
+
+void
+MovingTracer::onShapeEdge(Shape** shapep)
+{
+    Shape* shape = *shapep;
+    if (IsForwarded(shape))
+        *shapep = Forwarded(shape);
 }
 
 void
 Zone::prepareForCompacting()
 {
     FreeOp* fop = runtimeFromMainThread()->defaultFreeOp();
     discardJitCode(fop);
 }
@@ -2533,21 +2548,18 @@ ArenasToUpdate::updateKind(AllocKind kin
         return NONE;
     }
 
     // We try to update as many GC things in parallel as we can, but there are
     // kinds for which this might not be safe:
     //  - we assume JSObjects that are foreground finalized are not safe to
     //    update in parallel
     //  - updating a shape touches child shapes in fixupShapeTreeAfterMovingGC()
-    if (!js::gc::IsBackgroundFinalized(kind) ||
-        kind == AllocKind::SHAPE || kind == AllocKind::ACCESSOR_SHAPE)
-    {
+    if (!js::gc::IsBackgroundFinalized(kind) || IsShapeAllocKind(kind))
         return FOREGROUND;
-    }
 
     return BACKGROUND;
 }
 
 bool
 ArenasToUpdate::shouldProcessKind(AllocKind kind)
 {
     return (updateKind(kind) & kinds) != 0;
@@ -2721,16 +2733,21 @@ GCRuntime::updatePointersToRelocatedCell
     gcstats::AutoPhase ap(stats, gcstats::PHASE_COMPACT_UPDATE);
     MovingTracer trc(rt);
 
     // Fixup compartment global pointers as these get accessed during marking.
     for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
         comp->fixupAfterMovingGC();
     JSCompartment::fixupCrossCompartmentWrappersAfterMovingGC(&trc);
 
+    // Iterate through all cells that can contain relocatable pointers to update
+    // them. Since updating each cell is independent we try to parallelize this
+    // as much as possible.
+    updateAllCellPointers(&trc, zone);
+
     // Mark roots to update them.
     {
         markRuntime(&trc, MarkRuntime);
 
         gcstats::AutoPhase ap(stats, gcstats::PHASE_MARK_ROOTS);
         Debugger::markAll(&trc);
         Debugger::markIncomingCrossCompartmentEdges(&trc);
 
@@ -2760,21 +2777,16 @@ GCRuntime::updatePointersToRelocatedCell
     // TODO: Should possibly just call purgeRuntime() here.
     rt->newObjectCache.purge();
     rt->nativeIterCache.purge();
 
     // Call callbacks to get the rest of the system to fixup other untraced pointers.
     callWeakPointerZoneGroupCallbacks();
     for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
         callWeakPointerCompartmentCallbacks(comp);
-
-    // Finally, iterate through all cells that can contain JSObject pointers to
-    // update them. Since updating each cell is independent we try to
-    // parallelize this as much as possible.
-    updateAllCellPointers(&trc, zone);
 }
 
 void
 GCRuntime::protectAndHoldArenas(Arena* arenaList)
 {
     for (Arena* arena = arenaList; arena; ) {
         MOZ_ASSERT(arena->allocated());
         Arena* next = arena->next;
@@ -7326,16 +7338,26 @@ void
 js::gc::CheckHashTablesAfterMovingGC(JSRuntime* rt)
 {
     /*
      * Check that internal hash tables no longer have any pointers to things
      * that have been moved.
      */
     for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) {
         zone->checkUniqueIdTableAfterMovingGC();
+
+        // ZoneCellIter could GC were this not called under GC.
+        MOZ_ASSERT(rt->isHeapBusy());
+        JS::AutoSuppressGCAnalysis noAnalysis;
+
+        for (ZoneCellIter i(zone, AllocKind::BASE_SHAPE); !i.done(); i.next()) {
+            BaseShape* baseShape = i.get<BaseShape>();
+            if (baseShape->hasTable())
+                baseShape->table().checkAfterMovingGC();
+        }
     }
     for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
         c->objectGroups.checkTablesAfterMovingGC();
         c->checkInitialShapesTableAfterMovingGC();
         c->checkWrapperMapAfterMovingGC();
         c->checkBaseShapeTableAfterMovingGC();
         if (c->debugScopes)
             c->debugScopes->checkHashTablesAfterMovingGC(rt);
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1079,27 +1079,40 @@ class RelocationOverlay
         return next_;
     }
 
     static bool isCellForwarded(Cell* cell) {
         return fromCell(cell)->isForwarded();
     }
 };
 
-/* Functions for checking and updating things that might be moved by compacting GC. */
+// Functions for checking and updating GC thing pointers that might have been
+// moved by compacting GC. Overloads are also provided that work with Values.
+//
+// IsForwarded    - check whether a pointer refers to an GC thing that has been
+//                  moved.
+//
+// Forwarded      - return a pointer to the new location of a GC thing given a
+//                  pointer to old location.
+//
+// MaybeForwarded - used before dereferencing a pointer that may refer to a
+//                  moved GC thing without updating it. For JSObjects this will
+//                  also update the object's shape pointer if it has been moved
+//                  to allow slots to be accessed.
 
 template <typename T>
 struct MightBeForwarded
 {
     static_assert(mozilla::IsBaseOf<Cell, T>::value,
                   "T must derive from Cell");
     static_assert(!mozilla::IsSame<Cell, T>::value && !mozilla::IsSame<TenuredCell, T>::value,
                   "T must not be Cell or TenuredCell");
 
-    static const bool value = mozilla::IsBaseOf<JSObject, T>::value;
+    static const bool value = mozilla::IsBaseOf<JSObject, T>::value ||
+                              mozilla::IsBaseOf<Shape, T>::value;
 };
 
 template <typename T>
 inline bool
 IsForwarded(T* t)
 {
     RelocationOverlay* overlay = RelocationOverlay::fromCell(t);
     if (!MightBeForwarded<T>::value) {
@@ -1136,21 +1149,33 @@ struct ForwardedFunctor : public Identit
 };
 
 inline Value
 Forwarded(const JS::Value& value)
 {
     return DispatchTyped(ForwardedFunctor(), value);
 }
 
+inline void
+MakeAccessibleAfterMovingGC(void* anyp) {}
+
+inline void
+MakeAccessibleAfterMovingGC(JSObject* obj) {
+    if (obj->isNative())
+        obj->as<NativeObject>().updateShapeAfterMovingGC();
+}
+
 template <typename T>
 inline T
 MaybeForwarded(T t)
 {
-    return IsForwarded(t) ? Forwarded(t) : t;
+    if (IsForwarded(t))
+        t = Forwarded(t);
+    MakeAccessibleAfterMovingGC(t);
+    return t;
 }
 
 #ifdef JSGC_HASH_TABLE_CHECKS
 
 template <typename T>
 inline void
 CheckGCThingAfterMovingGC(T* t)
 {
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3785,19 +3785,16 @@ template<> const char16_t JS::ubi::Trace
     MOZ_UTF16("JSObject");
 
 void
 JSObject::traceChildren(JSTracer* trc)
 {
     TraceEdge(trc, &group_, "group");
 
     const Class* clasp = group_->clasp();
-    if (clasp->trace)
-        clasp->trace(trc, this);
-
     if (clasp->isNative()) {
         NativeObject* nobj = &as<NativeObject>();
 
         TraceEdge(trc, &nobj->shape_, "shape");
 
         {
             GetObjectSlotNameFunctor func(nobj);
             JS::AutoTracingDetails ctx(trc, func);
@@ -3823,16 +3820,21 @@ JSObject::traceChildren(JSTracer* trc)
             }
 
             TraceRange(trc,
                        nobj->getDenseInitializedLength(),
                        static_cast<HeapSlot*>(nobj->getDenseElementsAllowCopyOnWrite()),
                        "objectElements");
         } while (false);
     }
+
+    // Call the trace hook at the end so that during a moving GC the trace hook
+    // will see updated fields and slots.
+    if (clasp->trace)
+        clasp->trace(trc, this);
 }
 
 static JSAtom*
 displayAtomFromObjectGroup(ObjectGroup& group)
 {
     TypeNewScript* script = group.newScript();
     if (!script)
         return nullptr;
--- a/js/src/jspropertytree.cpp
+++ b/js/src/jspropertytree.cpp
@@ -243,29 +243,30 @@ Shape::fixupDictionaryShapeAfterMovingGC
 
 #ifdef DEBUG
     // Check that we got this right by interrogating the arena.
     // We use a fake cell pointer for this: it might not point to the beginning
     // of a cell, but will point into the right arena and will have the right
     // alignment.
     Cell* cell = reinterpret_cast<Cell*>(uintptr_t(listp) & ~CellMask);
     AllocKind kind = TenuredCell::fromPointer(cell)->getAllocKind();
-    MOZ_ASSERT_IF(listpPointsIntoShape,
-                  kind == AllocKind::SHAPE || kind == AllocKind::ACCESSOR_SHAPE);
+    MOZ_ASSERT_IF(listpPointsIntoShape, IsShapeAllocKind(kind));
     MOZ_ASSERT_IF(!listpPointsIntoShape, IsObjectAllocKind(kind));
 #endif
 
     if (listpPointsIntoShape) {
         // listp points to the parent field of the next shape.
         Shape* next = reinterpret_cast<Shape*>(uintptr_t(listp) - offsetof(Shape, parent));
-        listp = &gc::MaybeForwarded(next)->parent;
+        if (gc::IsForwarded(next))
+            listp = &gc::Forwarded(next)->parent;
     } else {
         // listp points to the shape_ field of an object.
         JSObject* last = reinterpret_cast<JSObject*>(uintptr_t(listp) - JSObject::offsetOfShape());
-        listp = &gc::MaybeForwarded(last)->as<NativeObject>().shape_;
+        if (gc::IsForwarded(last))
+            listp = &gc::Forwarded(last)->as<NativeObject>().shape_;
     }
 }
 
 void
 Shape::fixupShapeTreeAfterMovingGC()
 {
     if (kids.isNull())
         return;
@@ -313,16 +314,24 @@ Shape::fixupAfterMovingGC()
 {
     if (inDictionary())
         fixupDictionaryShapeAfterMovingGC();
     else
         fixupShapeTreeAfterMovingGC();
 }
 
 void
+BaseShape::fixupAfterMovingGC()
+{
+    if (hasTable())
+        table().fixupAfterMovingGC();
+}
+
+
+void
 Shape::fixupGetterSetterForBarrier(JSTracer* trc)
 {
     if (!hasGetterValue() && !hasSetterValue())
         return;
 
     JSObject* priorGetter = asAccessorShape().getterObj;
     JSObject* priorSetter = asAccessorShape().setterObj;
     if (!priorGetter && !priorSetter)
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -6367,18 +6367,17 @@ ShellBuildId(JS::BuildIdCharVector* buil
     const char buildid[] = "JS-shell";
     return buildId->append(buildid, sizeof(buildid));
 }
 
 static const JS::AsmJSCacheOps asmJSCacheOps = {
     ShellOpenAsmJSCacheEntryForRead,
     ShellCloseAsmJSCacheEntryForRead,
     ShellOpenAsmJSCacheEntryForWrite,
-    ShellCloseAsmJSCacheEntryForWrite,
-    ShellBuildId
+    ShellCloseAsmJSCacheEntryForWrite
 };
 
 static JSContext*
 NewContext(JSRuntime* rt)
 {
     JSContext* cx = JS_NewContext(rt, gStackChunkSize);
     if (!cx)
         return nullptr;
@@ -7264,16 +7263,17 @@ main(int argc, char** argv, char** envp)
     if (availMem > 0)
         JS_SetGCParametersBasedOnAvailableMemory(rt, availMem);
 
     JS_SetTrustedPrincipals(rt, &ShellPrincipals::fullyTrusted);
     JS_SetSecurityCallbacks(rt, &ShellPrincipals::securityCallbacks);
     JS_InitDestroyPrincipalsCallback(rt, ShellPrincipals::destroy);
 
     JS_SetInterruptCallback(rt, ShellInterruptCallback);
+    JS::SetBuildIdOp(rt, ShellBuildId);
     JS::SetAsmJSCacheOps(rt, &asmJSCacheOps);
 
     JS_SetNativeStackQuota(rt, gMaxStackSize);
 
     JS::dbg::SetDebuggerMallocSizeOf(rt, moz_malloc_size_of);
 
     if (!offThreadState.init())
         return 1;
--- a/js/src/tests/jstests.list
+++ b/js/src/tests/jstests.list
@@ -380,11 +380,8 @@ skip script test262/ch13/13.0/13.0_4-17g
 skip script test262/ch13/13.1/13.1-1gs.js
 skip script test262/ch13/13.1/13.1-4gs.js
 skip script test262/ch13/13.1/13.1-5gs.js
 skip script test262/ch13/13.1/13.1-8gs.js
 skip script test262/ch13/13.1/13.1-13gs.js
 skip script test262/ch13/13.2/13.2-19-b-3gs.js
 skip script test262/ch14/14.1/14.1-4gs.js
 skip script test262/ch14/14.1/14.1-5gs.js
-
-# Bug 917508: fails on Android x86 emulator
-skip-if(Android&&AndroidVersion>=17) script test262/ch11/11.5/11.5.3/S11.5.3_A4_T2.js
--- a/js/src/vm/NativeObject-inl.h
+++ b/js/src/vm/NativeObject-inl.h
@@ -281,16 +281,24 @@ NativeObject::setSlotWithType(ExclusiveC
     setSlot(shape->slot(), value);
 
     if (overwriting)
         shape->setOverwritten();
 
     AddTypePropertyId(cx, this, shape->propid(), value);
 }
 
+inline void
+NativeObject::updateShapeAfterMovingGC()
+{
+    Shape* shape = shape_.unbarrieredGet();
+    if (IsForwarded(shape))
+        shape_.unsafeSet(Forwarded(shape));
+}
+
 /* Make an object with pregenerated shape from a NEWOBJECT bytecode. */
 static inline PlainObject*
 CopyInitializerObject(JSContext* cx, HandlePlainObject baseobj, NewObjectKind newKind = GenericObject)
 {
     MOZ_ASSERT(!baseobj->inDictionaryMode());
 
     gc::AllocKind allocKind = gc::GetGCObjectFixedSlotsKind(baseobj->numFixedSlots());
     allocKind = gc::GetBackgroundAllocKind(allocKind);
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -1248,16 +1248,18 @@ class NativeObject : public JSObject
     inline void* getPrivate(uint32_t nfixed) const {
         return privateRef(nfixed);
     }
 
     static inline NativeObject*
     copy(ExclusiveContext* cx, gc::AllocKind kind, gc::InitialHeap heap,
          HandleNativeObject templateObject);
 
+    void updateShapeAfterMovingGC();
+
     /* JIT Accessors */
     static size_t offsetOfElements() { return offsetof(NativeObject, elements_); }
     static size_t offsetOfFixedElements() {
         return sizeof(NativeObject) + sizeof(ObjectElements);
     }
 
     static size_t getFixedSlotOffset(size_t slot) {
         return sizeof(NativeObject) + slot * sizeof(Value);
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -204,16 +204,17 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
     canUseSignalHandlers_(false),
     defaultFreeOp_(thisFromCtor()),
     debuggerMutations(0),
     securityCallbacks(&NullSecurityCallbacks),
     DOMcallbacks(nullptr),
     destroyPrincipals(nullptr),
     readPrincipals(nullptr),
     errorReporter(nullptr),
+    buildIdOp(nullptr),
     propertyRemovals(0),
 #if !EXPOSE_INTL_API
     thousandsSeparator(0),
     decimalSeparator(0),
     numGrouping(0),
 #endif
     mathCache_(nullptr),
     activeCompilations_(0),
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -1234,16 +1234,18 @@ struct JSRuntime : public JS::shadow::Ru
     const JSSecurityCallbacks* securityCallbacks;
     const js::DOMCallbacks* DOMcallbacks;
     JSDestroyPrincipalsOp destroyPrincipals;
     JSReadPrincipalsOp readPrincipals;
 
     /* Optional error reporter. */
     JSErrorReporter     errorReporter;
 
+    JS::BuildIdOp buildIdOp;
+
     /* AsmJSCache callbacks are runtime-wide. */
     JS::AsmJSCacheOps   asmJSCacheOps;
 
     /*
      * The propertyRemovals counter is incremented for every JSObject::clear,
      * and for each JSObject::remove method call that frees a slot in the given
      * object. See js_NativeGet and js_NativeSet in jsobj.cpp.
      */
--- a/js/src/vm/Shape.cpp
+++ b/js/src/vm/Shape.cpp
@@ -323,16 +323,42 @@ ShapeTable::grow(ExclusiveContext* cx)
             return false;
 
         cx->recoverFromOutOfMemory();
     }
 
     return true;
 }
 
+void
+ShapeTable::fixupAfterMovingGC()
+{
+    for (size_t i = 0; i < capacity(); i++) {
+        Entry& entry = getEntry(i);
+        Shape* shape = entry.shape();
+        if (shape && IsForwarded(shape))
+            entry.setPreservingCollision(Forwarded(shape));
+    }
+}
+
+#ifdef JSGC_HASH_TABLE_CHECKS
+
+void
+ShapeTable::checkAfterMovingGC()
+{
+    for (size_t i = 0; i < capacity(); i++) {
+        Entry& entry = getEntry(i);
+        Shape* shape = entry.shape();
+        if (shape)
+            CheckGCThingAfterMovingGC(shape);
+    }
+}
+
+#endif
+
 /* static */ Shape*
 Shape::replaceLastProperty(ExclusiveContext* cx, StackBaseShape& base,
                            TaggedProto proto, HandleShape shape)
 {
     MOZ_ASSERT(!shape->inDictionary());
 
     if (!shape->parent) {
         /* Treat as resetting the initial property of the shape hierarchy. */
@@ -1398,16 +1424,17 @@ JSCompartment::checkInitialShapesTableAf
      * initialShapes that points into the nursery, and that the hash table
      * entries are discoverable.
      */
     for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) {
         InitialShapeEntry entry = e.front();
         TaggedProto proto = entry.proto.unbarrieredGet();
         Shape* shape = entry.shape.unbarrieredGet();
 
+        CheckGCThingAfterMovingGC(shape);
         if (proto.isObject())
             CheckGCThingAfterMovingGC(proto.toObject());
 
         InitialShapeEntry::Lookup lookup(shape->getObjectClass(),
                                          proto,
                                          shape->numFixedSlots(),
                                          shape->getObjectFlags());
         InitialShapeSet::Ptr ptr = initialShapes.lookup(lookup);
@@ -1551,31 +1578,31 @@ JSCompartment::sweepInitialShapeTable()
 
 void
 JSCompartment::fixupInitialShapeTable()
 {
     if (!initialShapes.initialized())
         return;
 
     for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) {
+        // The shape may have been moved, but we can update that in place.
+        Shape* shape = e.front().shape.unbarrieredGet();
+        if (IsForwarded(shape)) {
+            shape = Forwarded(shape);
+            e.mutableFront().shape.set(shape);
+        }
+
+        // If the prototype has moved we have to rekey the entry.
         InitialShapeEntry entry = e.front();
-        bool needRekey = false;
-        if (IsForwarded(entry.shape.unbarrieredGet())) {
-            entry.shape.set(Forwarded(entry.shape.unbarrieredGet()));
-            needRekey = true;
-        }
         if (entry.proto.isObject() && IsForwarded(entry.proto.toObject())) {
             entry.proto = TaggedProto(Forwarded(entry.proto.toObject()));
-            needRekey = true;
-        }
-        if (needRekey) {
-            InitialShapeEntry::Lookup relookup(entry.shape.unbarrieredGet()->getObjectClass(),
+            InitialShapeEntry::Lookup relookup(shape->getObjectClass(),
                                                entry.proto,
-                                               entry.shape.unbarrieredGet()->numFixedSlots(),
-                                               entry.shape.unbarrieredGet()->getObjectFlags());
+                                               shape->numFixedSlots(),
+                                               shape->getObjectFlags());
             e.rekeyFront(relookup, entry);
         }
     }
 }
 
 void
 AutoRooterGetterSetter::Inner::trace(JSTracer* trc)
 {
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -223,16 +223,21 @@ class ShapeTable {
      * order to update the malloc counter on success.
      */
     bool init(ExclusiveContext* cx, Shape* lastProp);
     bool change(int log2Delta, ExclusiveContext* cx);
 
     template<MaybeAdding Adding>
     Entry& search(jsid id);
 
+    void fixupAfterMovingGC();
+#ifdef JSGC_HASH_TABLE_CHECKS
+    void checkAfterMovingGC();
+#endif
+
   private:
     Entry& getEntry(uint32_t i) const {
         MOZ_ASSERT(i < capacity());
         return entries_[i];
     }
     void decEntryCount() {
         MOZ_ASSERT(entryCount_ > 0);
         entryCount_--;
@@ -445,17 +450,17 @@ class BaseShape : public gc::TenuredCell
 
     /* For JIT usage */
     static inline size_t offsetOfFlags() { return offsetof(BaseShape, flags); }
 
     static const JS::TraceKind TraceKind = JS::TraceKind::BaseShape;
 
     void traceChildren(JSTracer* trc);
 
-    void fixupAfterMovingGC() {}
+    void fixupAfterMovingGC();
 
   private:
     static void staticAsserts() {
         JS_STATIC_ASSERT(offsetof(BaseShape, clasp_) == offsetof(js::shadow::BaseShape, clasp_));
         static_assert(sizeof(BaseShape) % gc::CellSize == 0,
                       "Things inheriting from gc::Cell must have a size that's "
                       "a multiple of gc::CellSize");
     }
--- a/js/src/vm/Xdr.cpp
+++ b/js/src/vm/Xdr.cpp
@@ -1,25 +1,28 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "vm/Xdr.h"
 
+#include "mozilla/PodOperations.h"
+
 #include <string.h>
 
 #include "jsapi.h"
 #include "jsscript.h"
 
 #include "vm/Debugger.h"
 #include "vm/ScopeObject.h"
 
 using namespace js;
+using mozilla::PodEqual;
 
 void
 XDRBuffer::freeBuffer()
 {
     js_free(base);
 #ifdef DEBUG
     memset(this, 0xe2, sizeof *this);
 #endif
@@ -87,29 +90,58 @@ XDRState<mode>::codeChars(char16_t* char
     }
     return true;
 }
 
 template<XDRMode mode>
 static bool
 VersionCheck(XDRState<mode>* xdr)
 {
-    uint32_t bytecodeVer;
+    JS::BuildIdCharVector buildId;
+    if (!xdr->cx()->buildIdOp() || !xdr->cx()->buildIdOp()(&buildId)) {
+        JS_ReportErrorNumber(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BUILD_ID_NOT_AVAILABLE);
+        return false;
+    }
+    MOZ_ASSERT(!buildId.empty());
+
+    uint32_t buildIdLength;
     if (mode == XDR_ENCODE)
-        bytecodeVer = XDR_BYTECODE_VERSION;
+        buildIdLength = buildId.length();
 
-    if (!xdr->codeUint32(&bytecodeVer))
+    if (!xdr->codeUint32(&buildIdLength))
         return false;
 
-    if (mode == XDR_DECODE && bytecodeVer != XDR_BYTECODE_VERSION) {
-        /* We do not provide binary compatibility with older scripts. */
-        JS_ReportErrorNumber(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BAD_SCRIPT_MAGIC);
+    if (mode == XDR_DECODE && buildIdLength != buildId.length()) {
+        JS_ReportErrorNumber(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BAD_BUILD_ID);
         return false;
     }
 
+    if (mode == XDR_ENCODE) {
+        if (!xdr->codeBytes(buildId.begin(), buildIdLength))
+            return false;
+    } else {
+        JS::BuildIdCharVector decodedBuildId;
+
+        // buildIdLength is already checked against the length of current
+        // buildId.
+        if (!decodedBuildId.resize(buildIdLength)) {
+            ReportOutOfMemory(xdr->cx());
+            return false;
+        }
+
+        if (!xdr->codeBytes(decodedBuildId.begin(), buildIdLength))
+            return false;
+
+        if (!PodEqual(decodedBuildId.begin(), buildId.begin(), buildIdLength)) {
+            // We do not provide binary compatibility with older scripts.
+            JS_ReportErrorNumber(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BAD_BUILD_ID);
+            return false;
+        }
+    }
+
     return true;
 }
 
 template<XDRMode mode>
 bool
 XDRState<mode>::codeFunction(MutableHandleFunction objp)
 {
     if (mode == XDR_DECODE)
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -10,42 +10,16 @@
 #include "mozilla/Endian.h"
 #include "mozilla/TypeTraits.h"
 
 #include "jsatom.h"
 #include "jsfriendapi.h"
 
 namespace js {
 
-/*
- * Bytecode version number. Increment the subtrahend whenever JS bytecode
- * changes incompatibly.
- *
- * This version number is XDR'd near the front of xdr bytecode and aborts
- * deserialization if there is a mismatch between the current and saved
- * versions.  If deserialization fails, the data should be invalidated if
- * possible.
- *
- * When you change this, run make_opcode_doc.py and copy the new output into
- * this wiki page:
- *
- *  https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
- *
- * (If you're wondering, 0xb973c0de is used because it looks like "bytecode".)
- */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 354;
-static const uint32_t XDR_BYTECODE_VERSION =
-    uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
-
-static_assert(JSErr_Limit == 419,
-              "GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
-              "removed MSG_DEFs from js.msg, you should increment "
-              "XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "
-              "expected JSErr_Limit value.");
-
 class XDRBuffer {
   public:
     explicit XDRBuffer(JSContext* cx)
       : context(cx), base(nullptr), cursor(nullptr), limit(nullptr) { }
 
     JSContext* cx() const {
         return context;
     }
--- a/js/src/vm/make_opcode_doc.py
+++ b/js/src/vm/make_opcode_doc.py
@@ -1,14 +1,14 @@
 #!/usr/bin/python -B
 
 """ Usage: make_opcode_doc.py PATH_TO_MOZILLA_CENTRAL
 
     This script generates SpiderMonkey bytecode documentation
-    from js/src/vm/Opcodes.h and js/src/vm/Xdr.h.
+    from js/src/vm/Opcodes.h.
 
     Output is written to stdout and should be pasted into the following
     MDN page:
     https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
 """
 
 from __future__ import print_function
 import re
@@ -16,35 +16,16 @@ import sys
 from xml.sax.saxutils import escape
 
 SOURCE_BASE = 'http://mxr.mozilla.org/mozilla-central/source'
 
 def error(message):
     print("Error: {message}".format(message=message), file=sys.stderr)
     sys.exit(1)
 
-def get_xdr_version(dir):
-    subtrahend_pat = re.compile('XDR_BYTECODE_VERSION_SUBTRAHEND\s*=\s*(\d+);', re.S)
-    version_expr_pat = re.compile('XDR_BYTECODE_VERSION\s*=\s*uint32_t\(0xb973c0de\s*-\s*(.+?)\);', re.S)
-
-    with open('{dir}/js/src/vm/Xdr.h'.format(dir=dir), 'r') as f:
-        data = f.read()
-
-    m = subtrahend_pat.search(data)
-    if not m:
-        error('XDR_BYTECODE_VERSION_SUBTRAHEND is not recognized.')
-
-    subtrahend = int(m.group(1))
-
-    m = version_expr_pat.search(data)
-    if not m:
-        error('XDR_BYTECODE_VERSION is not recognized.')
-
-    return subtrahend
-
 quoted_pat = re.compile(r"([^A-Za-z0-9]|^)'([^']+)'")
 js_pat = re.compile(r"([^A-Za-z0-9]|^)(JS[A-Z0-9_\*]+)")
 def codify(text):
     text = re.sub(quoted_pat, '\\1<code>\\2</code>', text)
     text = re.sub(js_pat, '\\1<code>\\2</code>', text)
 
     return text
 
@@ -350,31 +331,25 @@ def make_element_id(category, type=''):
         id_count[id] += 1
         id = '{}_{}'.format(id, id_count[id])
     else:
         id_count[id] = 1
 
     id_cache[key] = id
     return id
 
-def print_doc(version, index):
+def print_doc(index):
     print("""<div>{{{{SpiderMonkeySidebar("Internals")}}}}</div>
 
 <h2 id="Bytecode_Listing">Bytecode Listing</h2>
 
 <p>This document is automatically generated from
-<a href="{source_base}/js/src/vm/Opcodes.h">Opcodes.h</a> and
-<a href="{source_base}/js/src/vm/Xdr.h">Xdr.h</a> by
+<a href="{source_base}/js/src/vm/Opcodes.h">Opcodes.h</a> by
 <a href="{source_base}/js/src/vm/make_opcode_doc.py">make_opcode_doc.py</a>.</p>
-
-<p>Bytecode version: <code>{version}</code>
-(<code>0x{actual_version:08x}</code>).</p>
-""".format(source_base=SOURCE_BASE,
-           version=version,
-           actual_version=0xb973c0de - version))
+""".format(source_base=SOURCE_BASE))
 
     for (category_name, types) in index:
         print('<h3 id="{id}">{name}</h3>'.format(name=category_name,
                                                  id=make_element_id(category_name)))
         for (type_name, opcodes) in types:
             if type_name:
                 print('<h4 id="{id}">{name}</h4>'.format(name=type_name,
                                                          id=make_element_id(category_name, type_name)))
@@ -385,11 +360,10 @@ def print_doc(version, index):
             print('</dl>')
 
 if __name__ == '__main__':
     if len(sys.argv) < 2:
         print("Usage: make_opcode_doc.py PATH_TO_MOZILLA_CENTRAL",
               file=sys.stderr)
         sys.exit(1)
     dir = sys.argv[1]
-    version = get_xdr_version(dir)
     index = get_opcodes(dir)
-    print_doc(version, index)
+    print_doc(index)
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -696,16 +696,19 @@ mozJSComponentLoader::ObjectForLocation(
 
         if (NS_SUCCEEDED(rv)) {
             LOG(("Successfully loaded %s from startupcache\n", nativePath.get()));
         } else {
             // This is ok, it just means the script is not yet in the
             // cache. Could mean that the cache was corrupted and got removed,
             // but either way we're going to write this out.
             writeToCache = true;
+            // ReadCachedScript and ReadCachedFunction may have set a pending
+            // exception.
+            JS_ClearPendingException(cx);
         }
     }
 
     if (!script && !function) {
         // The script wasn't in the cache , so compile it now.
         LOG(("Slow loading %s\n", nativePath.get()));
 
         // If aPropagateExceptions is true, then our caller wants us to propagate
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -651,18 +651,23 @@ mozJSSubScriptLoader::DoLoadSubScriptWit
 
     JSVersion version = JS_GetVersion(cx);
     nsAutoCString cachePath;
     cachePath.AppendPrintf("jssubloader/%d", version);
     PathifyURI(uri, cachePath);
 
     RootedFunction function(cx);
     RootedScript script(cx);
-    if (cache && !options.ignoreCache)
+    if (cache && !options.ignoreCache) {
         rv = ReadCachedScript(cache, cachePath, cx, mSystemPrincipal, &script);
+        if (NS_FAILED(rv)) {
+            // ReadCachedScript may have set a pending exception.
+            JS_ClearPendingException(cx);
+        }
+    }
 
     // If we are doing an async load, trigger it and bail out.
     if (!script && options.async) {
         return ReadScriptAsync(uri, targetObj, options.charset, serv,
                                reusingGlobal, !!cache, retval);
     }
 
     if (!script) {
--- a/layout/reftests/border-radius/reftest.list
+++ b/layout/reftests/border-radius/reftest.list
@@ -38,32 +38,32 @@ fuzzy-if(skiaContent,1,2728) == corner-4
 # Tests for border clipping
 fails == clipping-1.html clipping-1-ref.html # background color should completely fill box; bug 466572
 != clipping-2.html about:blank # background color clipped to inner/outer border, can't get
 # great tests for this due to antialiasing problems described in bug 466572
 fuzzy-if(skiaContent,1,13) == clipping-3.html clipping-3-ref.xhtml # edge of border-radius clips an underlying object's background
 
 # Tests for clipping the contents of replaced elements and overflow!=visible
 != clipping-4-ref.html clipping-4-notref.html
-fuzzy-if(true,1,20) fuzzy-if(cocoaWidget,1,180) fuzzy-if(Android&&browserIsRemote,7,169) fuzzy-if(Android&&!browserIsRemote,140,237) == clipping-4-canvas.html clipping-4-ref.html # bug 732535
+fuzzy-if(true,1,20) fuzzy-if(cocoaWidget,1,180) fuzzy-if(Android,140,237) == clipping-4-canvas.html clipping-4-ref.html # bug 732535
 fuzzy-if(Android,5,54) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,10) == clipping-4-image.html clipping-4-ref.html
 fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,10) fuzzy-if(skiaContent,1,77) == clipping-4-overflow-hidden.html clipping-4-ref.html
 == clipping-5-canvas.html clipping-5-refc.html
 fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) == clipping-5-image.html clipping-5-refi.html
 fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) fuzzy-if(skiaContent,1,77) == clipping-5-overflow-hidden.html clipping-5-ref.html
 fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) fuzzy-if(Android,5,21) fuzzy-if(skiaContent,1,77) == clipping-5-refi.html clipping-5-ref.html
-fuzzy-if(true,1,7) fuzzy-if(cocoaWidget,1,99) fuzzy-if(Android&&browserIsRemote,7,89) fuzzy-if(Android&&!browserIsRemote,99,115) fuzzy-if(skiaContent,1,77) == clipping-5-refc.html clipping-5-ref.html # bug 732535
+fuzzy-if(true,1,7) fuzzy-if(cocoaWidget,1,99) fuzzy-if(Android,99,115) fuzzy-if(skiaContent,1,77) == clipping-5-refc.html clipping-5-ref.html # bug 732535
 fuzzy-if(winWidget,105,71) fuzzy-if(Android,8,469) == clipping-6.html clipping-6-ref.html # PaintedLayer and MaskLayer with transforms that aren't identical
 fuzzy-if(true,2,29) fuzzy-if(Android,255,586) fuzzy-if(skiaContent,16,27) == clipping-7.html clipping-7-ref.html # ColorLayer and MaskLayer with transforms that aren't identical. Reference image rendered without using layers (which causes fuzzy failures).
 fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,5) == clipping-and-zindex-1.html clipping-and-zindex-1-ref.html
 fuzzy-if(cocoaWidget,1,4) == intersecting-clipping-1-canvas.html intersecting-clipping-1-refc.html
 == intersecting-clipping-1-image.html intersecting-clipping-1-refi.html
 == intersecting-clipping-1-overflow-hidden.html intersecting-clipping-1-ref.html
 fuzzy-if(Android,5,105) fuzzy-if(d2d,1,20) fuzzy-if(skiaContent,1,135) == intersecting-clipping-1-refi.html intersecting-clipping-1-ref.html
-fuzzy-if(true,1,33) fuzzy-if(cocoaWidget,1,332) fuzzy-if(Android&&browserIsRemote,7,310) fuzzy-if(Android&&!browserIsRemote,124,440) fuzzy-if(skiaContent,1,135) == intersecting-clipping-1-refc.html intersecting-clipping-1-ref.html # bug 732535
+fuzzy-if(true,1,33) fuzzy-if(cocoaWidget,1,332) fuzzy-if(Android,124,440) fuzzy-if(skiaContent,1,135) == intersecting-clipping-1-refc.html intersecting-clipping-1-ref.html # bug 732535
 
 # Inheritance
 == inherit-1.html inherit-1-ref.html # border-radius shouldn't inherit
 
 # Table elements
 == table-collapse-1.html table-collapse-1-ref.html # border-radius is ignored on internal table elements
 # when border-collapse: collapse
 
@@ -73,17 +73,17 @@ fuzzy-if(azureQuartz,1,3) skip-if(B2G||M
 # test that border-radius is reduced for scrollbars
 skip-if(B2G||Mulet) fails-if(Android) fuzzy-if(asyncPan&&!layersGPUAccelerated,12,12) fuzzy-if(browserIsRemote&&layersGPUAccelerated&&/^Windows\x20NT\x206\.1/.test(http.oscpu),12,12) fuzzy-if(skiaContent,1,50) == scrollbar-clamping-1.html scrollbar-clamping-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) fails-if(Android) == scrollbar-clamping-2.html scrollbar-clamping-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 
 # Test for bad corner joins.
 fuzzy-if(true,1,1) == corner-joins-1.xhtml corner-joins-1-ref.xhtml
 fuzzy(255,20) skip-if(B2G||Mulet) random-if(winWidget) fuzzy-if(skiaContent,255,610) HTTP(..) == corner-joins-2.xhtml corner-joins-2-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop
 
-skip-if(B2G||Mulet) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.2/.test(http.oscpu),1,20) fuzzy-if(Android&&browserIsRemote,7,146) fuzzy-if(Android&&!browserIsRemote,166,400) fuzzy-if(skiaContent,64,70) == scroll-1.html scroll-1-ref.html # see bug 732535 #Bug 959166 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.2/.test(http.oscpu),1,20) fuzzy-if(Android,166,400) fuzzy-if(skiaContent,64,70) == scroll-1.html scroll-1-ref.html # see bug 732535 #Bug 959166 # Initial mulet triage: parity with B2G/B2G Desktop
 
 == transforms-1.html transforms-1-ref.html
 
 == zero-radius-clip-1.html zero-radius-clip-ref.html
 
 == iframe-1.html iframe-1-ref.html
 
 # Test for antialiasing gaps between background and border
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1703,17 +1703,17 @@ needs-focus != 703186-1.html 703186-2.ht
 == 711359-1.html 711359-1-ref.html
 == 712849-1.html 712849-1-ref.html
 == 713856-static.html  713856-ref.html
 == 713856-dynamic.html 713856-ref.html
 == 714519-1-as.html 714519-1-ref.html
 == 714519-1-q.html 714519-1-ref.html
 == 714519-2-as.html 714519-2-ref.html
 == 714519-2-q.html 714519-2-ref.html
-skip-if(B2G||Mulet) fuzzy-if(true,1,21) fuzzy-if(cocoaWidget,1,170) fuzzy-if(Android&&browserIsRemote,7,157) == 718521.html 718521-ref.html # bug 760270 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) fuzzy-if(true,1,21) fuzzy-if(cocoaWidget,1,170) == 718521.html 718521-ref.html # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
 == 720987.html 720987-ref.html
 == 722888-1.html 722888-1-ref.html
 == 722923-1.html 722923-1-ref.html
 == 723484-1.html 723484-1-ref.html
 random-if(Android||(B2G&&browserIsRemote)||Mulet) == 728983-1.html 728983-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) == 729143-1.html 729143-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 == 731521-1.html 731521-1-ref.html
 needs-focus == 731726-1.html 731726-1-ref.html
--- a/layout/reftests/layers/reftest.list
+++ b/layout/reftests/layers/reftest.list
@@ -1,10 +1,10 @@
 == move-to-background-1.html move-to-background-1-ref.html
-fuzzy-if(cocoaWidget,2,6) random-if(Android&&!browserIsRemote) == component-alpha-exit-1.html component-alpha-exit-1-ref.html # bug 760275
+fuzzy-if(cocoaWidget,2,6) random-if(Android) == component-alpha-exit-1.html component-alpha-exit-1-ref.html # bug 760275
 != pull-background-1.html about:blank
 != pull-background-2.html about:blank
 != pull-background-3.html about:blank 
 != pull-background-4.html about:blank 
 != pull-background-5.html about:blank
 != pull-background-6.html about:blank
 # The animated-position tests are disabled for intermittent failures / passes, bug 1150941
 skip != pull-background-animated-position-1.html about:blank # Fails with event regions
--- a/layout/reftests/percent-overflow-sizing/reftest.list
+++ b/layout/reftests/percent-overflow-sizing/reftest.list
@@ -1,26 +1,26 @@
 == simpleHeight100.html greenbox.html
 == simpleAbsHeight.html greenbox.html
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollSimpleHeight.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollSimpleHeightQuirks-1.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollSimpleHeightQuirks-2.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollSimpleHeightQuirks-3.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollAbsHeight.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollAbsHeightQuirks.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollSimpleHeight.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollSimpleHeightQuirks-1.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollSimpleHeightQuirks-2.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollSimpleHeightQuirks-3.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollAbsHeight.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollAbsHeightQuirks.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
 == simpleHeight100D.html greenbox.html
 == simpleAbsHeightD.html greenbox.html
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollSimpleHeightD.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollSimpleHeightQuirks-1D.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollSimpleHeightQuirks-2D.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-random-if(transparentScrollbars) fuzzy-if(B2G,1,11) fails-if(Android&&browserIsRemote) == hScrollSimpleHeightQuirks-3D.html greenboxhbar.html # bug 650591, 732565, 1136304
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollAbsHeightD.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollAbsHeightQuirksD.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollSimpleHeightD.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollSimpleHeightQuirks-1D.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollSimpleHeightQuirks-2D.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+random-if(transparentScrollbars) fuzzy-if(B2G,1,11) == hScrollSimpleHeightQuirks-3D.html greenboxhbar.html # bug 650591, 1136304
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollAbsHeightD.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollAbsHeightQuirksD.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
 == simpleMinHeight100D.html greenbox.html
 == simpleAbsMinHeightD.html greenbox.html
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollSimpleMinHeightD.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollSimpleMinHeightQuirks-1D.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollSimpleMinHeightQuirks-3D.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollAbsMinHeightD.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) == hScrollAbsMinHeightQuirksD.html greenboxhbar.html # bug 650591, 732565 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollSimpleMinHeightD.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollSimpleMinHeightQuirks-1D.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollSimpleMinHeightQuirks-3D.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollAbsMinHeightD.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) == hScrollAbsMinHeightQuirksD.html greenboxhbar.html # bug 650591 # bug 773482 # Initial mulet triage: parity with B2G/B2G Desktop
 == dynamicHeight100.html dynamicHeight100-ref.html
 == nestedHeight.html nestedHeight-ref.html
 == nestedHeightQuirks.html nestedHeightQuirks-ref.html
--- a/layout/reftests/scrolling/reftest.list
+++ b/layout/reftests/scrolling/reftest.list
@@ -1,19 +1,19 @@
 skip-if((B2G&&browserIsRemote)||Mulet) HTTP == deferred-anchor.xhtml#d deferred-anchor-ref.xhtml#d # Initial mulet triage: parity with B2G/B2G Desktop
 fuzzy-if(xulRuntime.widgetToolkit=="gtk3",1,23) == deferred-anchor2.xhtml deferred-anchor-ref.xhtml#d # bug 1182632
 HTTP == fixed-1.html fixed-1.html?ref
 fuzzy-if(skiaContent,1,30200) HTTP == fixed-table-1.html fixed-table-1.html?ref
 HTTP == fixed-opacity-1.html fixed-opacity-1.html?ref
 skip-if(B2G||Mulet) HTTP == fixed-opacity-2.html fixed-opacity-2.html?ref # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) random-if(gtkWidget) fuzzy-if(Android,3,60) HTTP == fixed-text-1.html fixed-text-1.html?ref # Initial mulet triage: parity with B2G/B2G Desktop
 HTTP == fixed-text-2.html fixed-text-2.html?ref
-random-if(Android&&!browserIsRemote) skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),1,12) == iframe-border-radius.html iframe-border-radius-ref.html # bug 760269 # Initial mulet triage: parity with B2G/B2G Desktop
+random-if(Android) skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),1,12) == iframe-border-radius.html iframe-border-radius-ref.html # bug 760269 # Initial mulet triage: parity with B2G/B2G Desktop
 random-if(Android) HTTP == image-1.html image-1.html?ref
-random-if(Android&&!browserIsRemote) HTTP == opacity-mixed-scrolling-1.html opacity-mixed-scrolling-1.html?ref # bug 760269
+random-if(Android) HTTP == opacity-mixed-scrolling-1.html opacity-mixed-scrolling-1.html?ref # bug 760269
 skip-if(B2G||Mulet) random-if(cocoaWidget) HTTP == opacity-mixed-scrolling-2.html opacity-mixed-scrolling-2.html?ref # see bug 625357 # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(Android) pref(layout.css.scroll-behavior.enabled,true) pref(layout.css.scroll-behavior.property-enabled,true) == scroll-behavior-1.html scroll-behavior-1.html?ref # see bug 1041833
 skip-if(Android) pref(layout.css.scroll-behavior.enabled,true) pref(layout.css.scroll-behavior.property-enabled,true) == scroll-behavior-2.html scroll-behavior-2.html?ref # see bug 1041833
 skip-if(Mulet) skip-if(Android) pref(layout.css.scroll-behavior.enabled,true) pref(layout.css.scroll-behavior.property-enabled,true) == scroll-behavior-3.html scroll-behavior-3.html?ref # see bug 1041833 # MULET: Bug 1144079: Re-enable Mulet mochitests and reftests taskcluster-specific disables
 skip-if(Mulet) skip-if(Android) pref(layout.css.scroll-behavior.enabled,true) pref(layout.css.scroll-behavior.property-enabled,true) == scroll-behavior-4.html scroll-behavior-4.html?ref # see bug 1041833 # MULET: Bug 1144079: Re-enable Mulet mochitests and reftests taskcluster-specific disables
 skip-if(Mulet) skip-if(Android) pref(layout.css.scroll-behavior.enabled,true) pref(layout.css.scroll-behavior.property-enabled,true) == scroll-behavior-5.html scroll-behavior-5.html?ref # see bug 1041833 # MULET: Bug 1144079: Re-enable Mulet mochitests and reftests taskcluster-specific disables
 skip-if(Android) pref(layout.css.scroll-behavior.enabled,true) pref(layout.css.scroll-behavior.property-enabled,true) == scroll-behavior-6.html scroll-behavior-6.html?ref # see bug 1041833
 skip-if(Android) pref(layout.css.scroll-behavior.enabled,true) pref(layout.css.scroll-behavior.property-enabled,true) == scroll-behavior-7.html scroll-behavior-7.html?ref # see bug 1041833
--- a/layout/xul/grid/reftests/reftest.list
+++ b/layout/xul/grid/reftests/reftest.list
@@ -8,11 +8,11 @@ skip-if((B2G&&browserIsRemote)||Mulet) f
 skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,60000) == not-full-basic.xul not-full-basic-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,110000) == not-full-grid-pack-align.xul not-full-basic-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,30000) == not-full-row-group-align.xul not-full-row-group-align-ref.xhtml # does anyone want/need this behavior? # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,10000) == not-full-row-group-pack.xul not-full-row-group-pack-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,50000) == not-full-row-group-direction.xul not-full-row-group-direction-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,60000) == not-full-row-leaf-align.xul not-full-basic-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,50000) == not-full-row-leaf-pack.xul not-full-row-leaf-pack-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,80000) == not-full-row-leaf-direction.xul not-full-row-leaf-pack-ref.xhtml
-skip-if(B2G||Mulet) random-if(transparentScrollbars) fails-if(Android&&browserIsRemote) fuzzy-if(OSX==1010,1,565) == scrollable-columns.xul scrollable-columns-ref.xhtml # bug 650597, 732569 # Initial mulet triage: parity with B2G/B2G Desktop
+skip-if(B2G||Mulet) random-if(transparentScrollbars) fuzzy-if(OSX==1010,1,565) == scrollable-columns.xul scrollable-columns-ref.xhtml # bug 650597 # Initial mulet triage: parity with B2G/B2G Desktop
 fails skip-if((B2G&&browserIsRemote)||Mulet) == scrollable-rows.xul scrollable-rows-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if((B2G&&browserIsRemote)||Mulet) == sizing-2d.xul sizing-2d-ref.xul # Initial mulet triage: parity with B2G/B2G Desktop
--- a/media/webrtc/trunk/webrtc/modules/audio_device/win/audio_device_core_win.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/win/audio_device_core_win.cc
@@ -2231,17 +2231,17 @@ int32_t AudioDeviceWindowsCore::InitPlay
         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cbSize         : %d", pWfxOut->cbSize);
     }
 
     // Set wave format
     Wfx.wFormatTag = WAVE_FORMAT_PCM;
     Wfx.wBitsPerSample = 16;
     Wfx.cbSize = 0;
 
-    const int freqs[] = {48000, 44100, 16000, 96000, 32000, 8000};
+    const int freqs[] = {48000, 44100, 32000, 96000, 16000, 8000};
     hr = S_FALSE;
 
     // Iterate over frequencies and channels, in order of priority
     for (int freq = 0; freq < sizeof(freqs)/sizeof(freqs[0]); freq++)
     {
         for (int chan = 0; chan < sizeof(_playChannelsPrioList)/sizeof(_playChannelsPrioList[0]); chan++)
         {
             Wfx.nChannels = _playChannelsPrioList[chan];
@@ -2568,17 +2568,17 @@ int32_t AudioDeviceWindowsCore::InitReco
         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cbSize         : %d", pWfxIn->cbSize);
     }
 
     // Set wave format
     Wfx.wFormatTag = WAVE_FORMAT_PCM;
     Wfx.wBitsPerSample = 16;
     Wfx.cbSize = 0;
 
-    const int freqs[6] = {48000, 44100, 16000, 96000, 32000, 8000};
+    const int freqs[6] = {48000, 44100, 32000, 96000, 16000, 8000};
     hr = S_FALSE;
 
     // Iterate over frequencies and channels, in order of priority
     for (int freq = 0; freq < sizeof(freqs)/sizeof(freqs[0]); freq++)
     {
         for (int chan = 0; chan < sizeof(_recChannelsPrioList)/sizeof(_recChannelsPrioList[0]); chan++)
         {
             Wfx.nChannels = _recChannelsPrioList[chan];
--- a/media/webrtc/trunk/webrtc/voice_engine/utility.cc
+++ b/media/webrtc/trunk/webrtc/voice_engine/utility.cc
@@ -81,17 +81,21 @@ void DownConvertToCodecFormat(const int1
                               AudioFrame* dst_af) {
   assert(samples_per_channel <= kMaxMonoDataSizeSamples);
   assert(num_channels == 1 || num_channels == 2);
   assert(codec_num_channels == 1 || codec_num_channels == 2);
   dst_af->Reset();
 
   // Never upsample the capture signal here. This should be done at the
   // end of the send chain.
-  int destination_rate = std::min(codec_rate_hz, sample_rate_hz);
+  // XXX bug 1247574 temporary hack until we switch to full-duplex
+  // We need to know the final audio rate before starting the audio channels,
+  // and this means we can get called back in Process() with the input
+  // rate if it's less than the codec rate.
+  int destination_rate = codec_rate_hz;
 
   // If no stereo codecs are in use, we downmix a stereo stream from the
   // device early in the chain, before resampling.
   if (num_channels == 2 && codec_num_channels == 1) {
     AudioFrameOperations::StereoToMono(src_data, samples_per_channel,
                                        mono_buffer);
     src_data = mono_buffer;
     num_channels = 1;
--- a/testing/mochitest/tests/SimpleTest/ChromeUtils.js
+++ b/testing/mochitest/tests/SimpleTest/ChromeUtils.js
@@ -109,63 +109,18 @@ function synthesizeCharAtPoint(aX, aY, a
  *   function (actualData, expectedData) {return boolean}
  *   @param actualData from dataTransfer
  *   @param expectedData from expectedDragData
  * see bug 462172 for example of use
  *
  */
 function synthesizeDragStart(element, expectedDragData, aWindow, x, y)
 {
-  if (!aWindow)
-    aWindow = window;
-  x = x || 2;
-  y = y || 2;
-  const step = 9;
-
-  var result = "trapDrag was not called";
-  var trapDrag = function(event) {
-    try {
-      var dataTransfer = event.dataTransfer;
-      result = null;
-      if (!dataTransfer)
-        throw "no dataTransfer";
-      if (expectedDragData == null ||
-          dataTransfer.mozItemCount != expectedDragData.length)
-        throw dataTransfer;
-      for (var i = 0; i < dataTransfer.mozItemCount; i++) {
-        var dtTypes = dataTransfer.mozTypesAt(i);
-        if (dtTypes.length != expectedDragData[i].length)
-          throw dataTransfer;
-        for (var j = 0; j < dtTypes.length; j++) {
-          if (dtTypes[j] != expectedDragData[i][j].type)
-            throw dataTransfer;
-          var dtData = dataTransfer.mozGetDataAt(dtTypes[j],i);
-          if (expectedDragData[i][j].eqTest) {
-            if (!expectedDragData[i][j].eqTest(dtData, expectedDragData[i][j].data))
-              throw dataTransfer;
-          }
-          else if (expectedDragData[i][j].data != dtData)
-            throw dataTransfer;
-        }
-      }
-    } catch(ex) {
-      result = ex;
-    }
-    event.preventDefault();
-    event.stopPropagation();
-  }
-  aWindow.addEventListener("dragstart", trapDrag, false);
-  EventUtils.synthesizeMouse(element, x, y, { type: "mousedown" }, aWindow);
-  x += step; y += step;
-  EventUtils.synthesizeMouse(element, x, y, { type: "mousemove" }, aWindow);
-  x += step; y += step;
-  EventUtils.synthesizeMouse(element, x, y, { type: "mousemove" }, aWindow);
-  aWindow.removeEventListener("dragstart", trapDrag, false);
-  EventUtils.synthesizeMouse(element, x, y, { type: "mouseup" }, aWindow);
-  return result;
+  return EventUtils.synthesizeDragStart(element, expectedDragData,
+                                        aWindow, x, y);
 }
 
 /**
  * INTERNAL USE ONLY
  * Create an event object to pass to EventUtils.sendDragEvent.
  *
  * @param aType          The string represents drag event type.
  * @param aDestElement   The element to fire the drag event, used to calculate
--- a/testing/mochitest/tests/SimpleTest/EventUtils.js
+++ b/testing/mochitest/tests/SimpleTest/EventUtils.js
@@ -1712,8 +1712,79 @@ function synthesizeNativeOSXClick(x, y)
   CGEventPost(kCGHIDEventTap, event);
   CFRelease(event);
 
   CFRelease(source);
 
   CoreFoundation.close();
   CoreGraphics.close();
 }
+
+/**
+ * Emulate a dragstart event.
+ *  element - element to fire the dragstart event on
+ *  expectedDragData - the data you expect the data transfer to contain afterwards
+ *                      This data is in the format:
+ *                         [ [ {type: value, data: value, test: function}, ... ], ... ]
+ *                     can be null
+ *  aWindow - optional; defaults to the current window object.
+ *  x - optional; initial x coordinate
+ *  y - optional; initial y coordinate
+ * Returns null if data matches.
+ * Returns the event.dataTransfer if data does not match
+ *
+ * eqTest is an optional function if comparison can't be done with x == y;
+ *   function (actualData, expectedData) {return boolean}
+ *   @param actualData from dataTransfer
+ *   @param expectedData from expectedDragData
+ * see bug 462172 for example of use
+ *
+ */
+function synthesizeDragStart(element, expectedDragData, aWindow, x, y)
+{
+  if (!aWindow)
+    aWindow = window;
+  x = x || 2;
+  y = y || 2;
+  const step = 9;
+
+  var result = "trapDrag was not called";
+  var trapDrag = function(event) {
+    try {
+      var dataTransfer = event.dataTransfer;
+      result = null;
+      if (!dataTransfer)
+        throw "no dataTransfer";
+      if (expectedDragData == null ||
+          dataTransfer.mozItemCount != expectedDragData.length)
+        throw dataTransfer;
+      for (var i = 0; i < dataTransfer.mozItemCount; i++) {
+        var dtTypes = dataTransfer.mozTypesAt(i);
+        if (dtTypes.length != expectedDragData[i].length)
+          throw dataTransfer;
+        for (var j = 0; j < dtTypes.length; j++) {
+          if (dtTypes[j] != expectedDragData[i][j].type)
+            throw dataTransfer;
+          var dtData = dataTransfer.mozGetDataAt(dtTypes[j],i);
+          if (expectedDragData[i][j].eqTest) {
+            if (!expectedDragData[i][j].eqTest(dtData, expectedDragData[i][j].data))
+              throw dataTransfer;
+          }
+          else if (expectedDragData[i][j].data != dtData)
+            throw dataTransfer;
+        }
+      }
+    } catch(ex) {
+      result = ex;
+    }
+    event.preventDefault();
+    event.stopPropagation();
+  }
+  aWindow.addEventListener("dragstart", trapDrag, false);
+  synthesizeMouse(element, x, y, { type: "mousedown" }, aWindow);
+  x += step; y += step;
+  synthesizeMouse(element, x, y, { type: "mousemove" }, aWindow);
+  x += step; y += step;
+  synthesizeMouse(element, x, y, { type: "mousemove" }, aWindow);
+  aWindow.removeEventListener("dragstart", trapDrag, false);
+  synthesizeMouse(element, x, y, { type: "mouseup" }, aWindow);
+  return result;
+}
--- a/testing/modules/AppInfo.jsm
+++ b/testing/modules/AppInfo.jsm
@@ -10,16 +10,19 @@ this.EXPORTED_SYMBOLS = [
   "updateAppInfo",
 ];
 
 
 const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
+let origPlatformInfo = Cc["@mozilla.org/xre/app-info;1"]
+    .getService(Ci.nsIPlatformInfo);
+
 /**
  * Create new XULAppInfo instance with specified options.
  *
  * options is a object with following keys:
  *   ID:              nsIXULAppInfo.ID
  *   name:            nsIXULAppInfo.name
  *   version:         nsIXULAppInfo.version
  *   platformVersion: nsIXULAppInfo.platformVersion
@@ -39,33 +42,36 @@ this.newAppInfo = function (options={}) 
 
   let appInfo = {
     // nsIXULAppInfo
     vendor: "Mozilla",
     name: name,
     ID: ID,
     version: version,
     appBuildID: "20160315",
+
+    // nsIPlatformInfo
     platformVersion: platformVersion,
-    platformBuildID: "20160316",
+    platformBuildID: origPlatformInfo.platformBuildID,
 
     // nsIXULRuntime
     inSafeMode: false,
     logConsoleErrors: true,
     OS: OS,
     XPCOMABI: "noarch-spidermonkey",
     invalidateCachesOnRestart() {},
 
     // nsIWinAppHelper
     get userCanElevate() {
       return false;
     },
   };
 
   let interfaces = [Ci.nsIXULAppInfo,
+                    Ci.nsIPlatformInfo,
                     Ci.nsIXULRuntime];
   if ("nsIWinAppHelper" in Ci) {
     interfaces.push(Ci.nsIWinAppHelper);
   }
 
   if ("crashReporter" in options && options.crashReporter) {
     // nsICrashReporter
     appInfo.annotations = {};
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -14,16 +14,17 @@ var Cc = Components.classes;
 var Cu = Components.utils;
 
 Cu.import("chrome://specialpowers/content/MockFilePicker.jsm");
 Cu.import("chrome://specialpowers/content/MockColorPicker.jsm");
 Cu.import("chrome://specialpowers/content/MockPermissionPrompt.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/NetUtil.jsm");
 
 // We're loaded with "this" not set to the global in some cases, so we
 // have to play some games to get at the global object here.  Normally
 // we'd try "this" from a function called with undefined this value,
 // but this whole file is in strict mode.  So instead fall back on
 // returning "this" from indirect eval, which returns the global.
 if (!(function() { var e = eval; return e("this"); })().File) {
     Cu.importGlobalProperties(["File"]);
@@ -1955,13 +1956,50 @@ SpecialPowersAPI.prototype = {
   allowMedia: function(window, enable) {
     this._getDocShell(window).allowMedia = enable;
   },
 
   createChromeCache: function(name, url) {
     let principal = this._getPrincipalFromArg(url);
     return wrapIfUnwrapped(new content.window.CacheStorage(name, principal));
   },
+
+  loadChannelAndReturnStatus: function(url, loadUsingSystemPrincipal) {
+    const BinaryInputStream =
+        Components.Constructor("@mozilla.org/binaryinputstream;1",
+                               "nsIBinaryInputStream",
+                               "setInputStream");
+
+    return new Promise(function(resolve) {
+      let listener = {
+        httpStatus : 0,
+
+        onStartRequest: function(request, context) {
+          request.QueryInterface(Ci.nsIHttpChannel);
+          this.httpStatus = request.responseStatus;
+        },
+
+        onDataAvailable: function(request, context, stream, offset, count) {
+          new BinaryInputStream(stream).readByteArray(count);
+        },
+
+        onStopRequest: function(request, context, status) {
+         /* testing here that the redirect was not followed. If it was followed
+            we would see a http status of 200 and status of NS_OK */
+
+          let httpStatus = this.httpStatus;
+          resolve({status, httpStatus});
+        }
+      };
+      let uri = NetUtil.newURI(url);
+      let channel = NetUtil.newChannel({uri, loadUsingSystemPrincipal});
+
+      channel.loadFlags |= Ci.nsIChannel.LOAD_DOCUMENT_URI;
+      channel.QueryInterface(Ci.nsIHttpChannelInternal);
+      channel.documentURI = uri;
+      channel.asyncOpen2(listener);
+    });
+  },
 };
 
 this.SpecialPowersAPI = SpecialPowersAPI;
 this.bindDOMWindowUtils = bindDOMWindowUtils;
 this.getRawComponents = getRawComponents;
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -63,16 +63,17 @@
 #include "nsIConsoleService.h"
 #include "nsIContentHandler.h"
 #include "nsIDialogParamBlock.h"
 #include "nsIDOMWindow.h"
 #include "mozilla/ModuleUtils.h"
 #include "nsIIOService2.h"
 #include "nsIObserverService.h"
 #include "nsINativeAppSupport.h"
+#include "nsIPlatformInfo.h"
 #include "nsIProcess.h"
 #include "nsIProfileUnlocker.h"
 #include "nsIPromptService.h"
 #include "nsIServiceManager.h"
 #include "nsIStringBundle.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIToolkitChromeRegistry.h"
 #include "nsIToolkitProfile.h"
@@ -737,16 +738,17 @@ class nsXULAppInfo : public nsIXULAppInf
                      public nsIFinishDumpingCallback,
 #endif
                      public nsIXULRuntime
 
 {
 public:
   MOZ_CONSTEXPR nsXULAppInfo() {}
   NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIPLATFORMINFO
   NS_DECL_NSIXULAPPINFO
   NS_DECL_NSIXULRUNTIME
   NS_DECL_NSIOBSERVER
 #ifdef MOZ_CRASHREPORTER
   NS_DECL_NSICRASHREPORTER
   NS_DECL_NSIFINISHDUMPINGCALLBACK
 #endif
 #ifdef XP_WIN
@@ -760,17 +762,18 @@ NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
 #ifdef XP_WIN
   NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
 #endif
 #ifdef MOZ_CRASHREPORTER
   NS_INTERFACE_MAP_ENTRY(nsICrashReporter)
   NS_INTERFACE_MAP_ENTRY(nsIFinishDumpingCallback)
 #endif
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData || 
+  NS_INTERFACE_MAP_ENTRY(nsIPlatformInfo)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo, gAppData ||
                                      XRE_IsContentProcess())
 NS_INTERFACE_MAP_END
 
 NS_IMETHODIMP_(MozExternalRefCountType)
 nsXULAppInfo::AddRef()
 {
   return 1;
 }
--- a/widget/gonk/nativewindow/GonkBufferQueueJB.cpp
+++ b/widget/gonk/nativewindow/GonkBufferQueueJB.cpp
@@ -418,17 +418,17 @@ status_t GonkBufferQueue::dequeueBuffer(
         *outFence = mSlots[buf].mFence;
         mSlots[buf].mFence = Fence::NO_FENCE;
     }  // end lock scope
 
     sp<GraphicBuffer> graphicBuffer;
     if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
 
         usage |= GraphicBuffer::USAGE_HW_TEXTURE;
-        ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
+        ClientIPCAllocator* allocator = ImageBridgeChild::GetSingleton();
         GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w,h), format,
                                                                  gfx::BackendType::NONE, usage,
                                                                  allocator);
         if (!texData) {
             ST_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
             return -ENOMEM;
         }
         RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
--- a/widget/gonk/nativewindow/GonkBufferQueueKK.cpp
+++ b/widget/gonk/nativewindow/GonkBufferQueueKK.cpp
@@ -437,17 +437,17 @@ status_t GonkBufferQueue::dequeueBuffer(
                     buf, buffer->width, buffer->height, buffer->format);
         }
         *outFence = mSlots[buf].mFence;
         mSlots[buf].mFence = Fence::NO_FENCE;
     }  // end lock scope
 
     if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
 
-        ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
+        ClientIPCAllocator* allocator = ImageBridgeChild::GetSingleton();
         usage |= GraphicBuffer::USAGE_HW_TEXTURE;
         GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w, h), format,
                                                                  gfx::BackendType::NONE, usage,
                                                                  allocator);
         if (!texData) {
             return -ENOMEM;
         }
 
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp
@@ -336,17 +336,17 @@ status_t GonkBufferQueueProducer::dequeu
                     found, buffer->width, buffer->height, buffer->format);
         }
 
         *outFence = mSlots[found].mFence;
         mSlots[found].mFence = Fence::NO_FENCE;
     } // Autolock scope
 
     if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
-        ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
+        ClientIPCAllocator* allocator = ImageBridgeChild::GetSingleton();
         usage |= GraphicBuffer::USAGE_HW_TEXTURE;
         GrallocTextureData* texData = GrallocTextureData::Create(IntSize(width,height), format,
                                                                  gfx::BackendType::NONE,
                                                                  usage, allocator);
         if (!texData) {
             ALOGE("dequeueBuffer: failed to alloc gralloc buffer");
             return -ENOMEM;
         }
--- a/widget/gonk/nativewindow/GonkNativeWindowICS.cpp
+++ b/widget/gonk/nativewindow/GonkNativeWindowICS.cpp
@@ -314,17 +314,17 @@ status_t GonkNativeWindow::dequeueBuffer
                 mSlots[buf].mTextureClient = NULL;
                 ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(FROM_HERE, task);
             }
             alloc = true;
         }
     }  // end lock scope
 
     if (alloc) {
-        ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
+        ClientIPCAllocator* allocator = ImageBridgeChild::GetSingleton();
         usage |= GraphicBuffer::USAGE_HW_TEXTURE;
         GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w, h), format,
                                                                  gfx::BackendType::NONE, usage,
                                                                  allocator);
         if (!texData) {
             return -ENOMEM;
         }
 
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -80,16 +80,17 @@
 #include "nsJSUtils.h"
 #include "nsWrapperCache.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 
 #include "nsIException.h"
+#include "nsIPlatformInfo.h"
 #include "nsThread.h"
 #include "nsThreadUtils.h"
 #include "xpcpublic.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 namespace mozilla {
@@ -404,16 +405,39 @@ NoteJSChildGrayWrapperShim(void* aData, 
 static const JSZoneParticipant sJSZoneCycleCollectorGlobal;
 
 static
 void JSObjectsTenuredCb(JSRuntime* aRuntime, void* aData)
 {
   static_cast<CycleCollectedJSRuntime*>(aData)->JSObjectsTenured();
 }
 
+bool
+mozilla::GetBuildId(JS::BuildIdCharVector* aBuildID)
+{
+  nsCOMPtr<nsIPlatformInfo> info = do_GetService("@mozilla.org/xre/app-info;1");
+  if (!info) {
+    return false;
+  }
+
+  nsCString buildID;
+  nsresult rv = info->GetPlatformBuildID(buildID);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  if (!aBuildID->resize(buildID.Length())) {
+    return false;
+  }
+
+  for (size_t i = 0; i < buildID.Length(); i++) {
+    (*aBuildID)[i] = buildID[i];
+  }
+
+  return true;
+}
+
 CycleCollectedJSRuntime::CycleCollectedJSRuntime()
   : mGCThingCycleCollectorGlobal(sGCThingCycleCollectorGlobal)
   , mJSZoneCycleCollectorGlobal(sJSZoneCycleCollectorGlobal)
   , mJSRuntime(nullptr)
   , mPrevGCSliceCallback(nullptr)
   , mPrevGCNurseryCollectionCallback(nullptr)
   , mJSHolders(256)
   , mDoingStableStates(false)
@@ -498,16 +522,17 @@ CycleCollectedJSRuntime::Initialize(JSRu
 
   JS_SetObjectsTenuredCallback(mJSRuntime, JSObjectsTenuredCb, this);
   JS::SetOutOfMemoryCallback(mJSRuntime, OutOfMemoryCallback, this);
   JS::SetLargeAllocationFailureCallback(mJSRuntime,
                                         LargeAllocationFailureCallback, this);
   JS_SetContextCallback(mJSRuntime, ContextCallback, this);
   JS_SetDestroyZoneCallback(mJSRuntime, XPCStringConvert::FreeZoneCache);
   JS_SetSweepZoneCallback(mJSRuntime, XPCStringConvert::ClearZoneCache);
+  JS::SetBuildIdOp(mJSRuntime, GetBuildId);
   // XPCJSRuntime currently overrides this because we don't
   // TakeOwnershipOfErrorReporting everwhere on the main thread yet.
   JS_SetErrorReporter(mJSRuntime, MozCrashErrorReporter);
 
   static js::DOMCallbacks DOMcallbacks = {
     InstanceClassHasProtoAtDepth
   };
   SetDOMCallbacks(mJSRuntime, &DOMcallbacks);
--- a/xpcom/base/CycleCollectedJSRuntime.h
+++ b/xpcom/base/CycleCollectedJSRuntime.h
@@ -412,11 +412,14 @@ private:
 void TraceScriptHolder(nsISupports* aHolder, JSTracer* aTracer);
 
 // Returns true if the JS::TraceKind is one the cycle collector cares about.
 inline bool AddToCCKind(JS::TraceKind aKind)
 {
   return aKind == JS::TraceKind::Object || aKind == JS::TraceKind::Script;
 }
 
+bool
+GetBuildId(JS::BuildIdCharVector* aBuildID);
+
 } // namespace mozilla
 
 #endif // mozilla_CycleCollectedJSRuntime_h__
--- a/xpcom/system/moz.build
+++ b/xpcom/system/moz.build
@@ -9,16 +9,17 @@ XPIDL_SOURCES += [
     'nsIDeviceSensors.idl',
     'nsIExternalApplication.idl',
     'nsIGConfService.idl',
     'nsIGeolocationProvider.idl',
     'nsIGIOService.idl',
     'nsIGSettingsService.idl',
     'nsIHapticFeedback.idl',
     'nsIPackageKitService.idl',
+    'nsIPlatformInfo.idl',
     'nsIXULAppInfo.idl',
     'nsIXULRuntime.idl',
 ]
 
 if CONFIG['MOZ_CRASHREPORTER']:
     XPIDL_SOURCES += [
         'nsICrashReporter.idl',
     ]
new file mode 100644
--- /dev/null
+++ b/xpcom/system/nsIPlatformInfo.idl
@@ -0,0 +1,19 @@
+/* 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(ab6650cf-0806-4aea-b8f2-40fdae74f1cc)]
+interface nsIPlatformInfo : nsISupports
+{
+  /**
+   * The version of the XULRunner platform.
+   */
+  readonly attribute ACString platformVersion;
+
+  /**
+   * The build ID/date of gecko and the XULRunner platform.
+   */
+  readonly attribute ACString platformBuildID;
+};
--- a/xpcom/system/nsIXULAppInfo.idl
+++ b/xpcom/system/nsIXULAppInfo.idl
@@ -1,21 +1,21 @@
 /* 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"
+#include "nsIPlatformInfo.idl"
 
 /**
  * A scriptable interface to the nsXULAppAPI structure. See nsXULAppAPI.h for
  * a detailed description of each attribute.
  */
 
-[scriptable, uuid(1518e7d2-022a-4dae-b02e-bbe7ffcf2145)]
-interface nsIXULAppInfo : nsISupports
+[scriptable, uuid(ddea4f31-3c5e-4769-ac68-21ab4b3d7845)]
+interface nsIXULAppInfo : nsIPlatformInfo
 {
   /**
    * @see nsXREAppData.vendor
    * @returns an empty string if nsXREAppData.vendor is not set.
    */
   readonly attribute ACString vendor;
 
   /**
@@ -41,23 +41,13 @@ interface nsIXULAppInfo : nsISupports
   /**
    * The build ID/date of the application. For xulrunner applications,
    * this will be different than the build ID of the platform. Be careful
    * about which one you want.
    */
   readonly attribute ACString appBuildID;
 
   /**
-   * The version of the XULRunner platform.
-   */
-  readonly attribute ACString platformVersion;
-
-  /**
-   * The build ID/date of gecko and the XULRunner platform.
-   */
-  readonly attribute ACString platformBuildID;
-  
-  /**
    * @see nsXREAppData.UAName
    * @returns an empty string if nsXREAppData.UAName is not set.
    */
   readonly attribute ACString UAName;
 };