Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Tue, 22 Mar 2016 16:45:43 -0700
changeset 289894 3381aa98edf72e02b9d6b4db6efa0865063a2329
parent 289893 5453ae837f6a9394f01f2219c3998098f23a41fb (current diff)
parent 289815 42c21bf6657b9e67b265813ab44162d874e12d9d (diff)
child 289895 eb528d042c851c297f40543d63dfb8d1ed5361ce
child 290030 f9e8d838c9ee9b5f71984b82e6cf4f312fa108a4
push id74027
push userkwierso@gmail.com
push dateTue, 22 Mar 2016 23:57:42 +0000
treeherdermozilla-inbound@eb528d042c85 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge 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;
 };