Merge mozilla-central to mozilla-inbound on a CLOSED TREE
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 11 Mar 2016 17:14:35 +0100
changeset 288290 c8b421423059068586d436fb7fbab9be5059faf5
parent 288289 28bca8e29596cfa1c24b864925cb5cb5e20e35ab (diff)
parent 288231 946ed22cad04431c75ab5093989dfedf1bae5a3e (current diff)
child 288291 d80794ec133731287eeadff04797d4cd93641509
push id30079
push userryanvm@gmail.com
push dateSat, 12 Mar 2016 20:24:19 +0000
treeherdermozilla-central@d1d47ba19ce9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
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 mozilla-central to mozilla-inbound on a CLOSED TREE
--- a/build/mobile/b2gautomation.py
+++ b/build/mobile/b2gautomation.py
@@ -33,23 +33,22 @@ class StdOutProc(ProcessHandlerMixin):
     def handle_output(self, line):
         self.queue.put_nowait(line)
 
 
 class B2GRemoteAutomation(Automation):
     _devicemanager = None
 
     def __init__(self, deviceManager, appName='', remoteLog=None,
-                 marionette=None, context_chrome=True):
+                 marionette=None):
         self._devicemanager = deviceManager
         self._appName = appName
         self._remoteProfile = None
         self._remoteLog = remoteLog
         self.marionette = marionette
-        self.context_chrome = context_chrome
         self._is_emulator = False
         self.test_script = None
         self.test_script_args = None
 
         # Default our product to b2g
         self._product = "b2g"
         self.lastTestSeen = "b2gautomation.py"
         # Default log finish to mochitest standard
@@ -351,46 +350,43 @@ class B2GRemoteAutomation(Automation):
         else:
             time.sleep(5)
 
         # start a marionette session
         session = self.marionette.start_session()
         if 'b2g' not in session:
             raise Exception("bad session value %s returned by start_session" % session)
 
-        self.marionette.set_context(self.marionette.CONTEXT_CHROME)
-        self.marionette.execute_script("""
-            let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
-            Components.utils.import("resource://gre/modules/Services.jsm");
-            Services.prefs.setBoolPref(SECURITY_PREF, true);
+        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
+            self.marionette.execute_script("""
+                let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
+                Components.utils.import("resource://gre/modules/Services.jsm");
+                Services.prefs.setBoolPref(SECURITY_PREF, true);
 
-            if (!testUtils.hasOwnProperty("specialPowersObserver")) {
-              let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
-                .getService(Components.interfaces.mozIJSSubScriptLoader);
-              loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.jsm",
-                testUtils);
-              testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
-              testUtils.specialPowersObserver.init();
-            }
-            """)
+                if (!testUtils.hasOwnProperty("specialPowersObserver")) {
+                  let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
+                    .getService(Components.interfaces.mozIJSSubScriptLoader);
+                  loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.jsm",
+                    testUtils);
+                  testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
+                  testUtils.specialPowersObserver.init();
+                }
+                """)
 
-        if not self.context_chrome:
-            self.marionette.set_context(self.marionette.CONTEXT_CONTENT)
-
-        # run the script that starts the tests
-        if self.test_script:
-            if os.path.isfile(self.test_script):
-                script = open(self.test_script, 'r')
-                self.marionette.execute_script(script.read(), script_args=self.test_script_args)
-                script.close()
-            elif isinstance(self.test_script, basestring):
-                self.marionette.execute_script(self.test_script, script_args=self.test_script_args)
-        else:
-            # assumes the tests are started on startup automatically
-            pass
+            # run the script that starts the tests
+            if self.test_script:
+                if os.path.isfile(self.test_script):
+                    script = open(self.test_script, 'r')
+                    self.marionette.execute_script(script.read(), script_args=self.test_script_args)
+                    script.close()
+                elif isinstance(self.test_script, basestring):
+                    self.marionette.execute_script(self.test_script, script_args=self.test_script_args)
+            else:
+                # assumes the tests are started on startup automatically
+                pass
 
         return instance
 
     # be careful here as this inner class doesn't have access to outer class members
     class B2GInstance(object):
         """Represents a B2G instance running on a device, and exposes
            some process-like methods/properties that are expected by the
            automation.
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -334,28 +334,28 @@ class RemoteAutomation(Automation):
                 testStartFilenames = re.findall(r"TEST-START \| ([^\s]*)", newLogContent)
                 if testStartFilenames:
                     self.lastTestSeen = testStartFilenames[-1]
                 print newLogContent
                 return True
 
             self.logBuffer += newLogContent
             lines = self.logBuffer.split('\n')
+            lines = [l for l in lines if l]
 
             if lines:
                 # We only keep the last (unfinished) line in the buffer
                 self.logBuffer = lines[-1]
                 del lines[-1]
 
             if not lines:
                 return False
 
             for line in lines:
                 # This passes the line to the logger (to be logged or buffered)
-                # and returns a list of structured messages (dict)
                 parsed_messages = self.messageLogger.write(line)
                 for message in parsed_messages:
                     if isinstance(message, dict) and message.get('action') == 'test_start':
                         self.lastTestSeen = message['test']
             return True
 
         @property
         def getLastTestSeen(self):
--- a/dom/base/DOMException.cpp
+++ b/dom/base/DOMException.cpp
@@ -172,26 +172,28 @@ NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Exception)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Exception)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(Exception)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Exception)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mData)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Exception)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mThrownJSVal)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Exception)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mData)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   tmp->mThrownJSVal.setNull();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CI_INTERFACE_GETTER(Exception, nsIXPCException)
 
 Exception::Exception(const nsACString& aMessage,
                      nsresult aResult,
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -16,16 +16,17 @@
 #include "mozilla/dom/MessageEvent.h"
 #include "mozilla/dom/MessageEventBinding.h"
 #include "mozilla/dom/nsCSPContext.h"
 #include "mozilla/dom/nsCSPUtils.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerRunnable.h"
 #include "mozilla/dom/WorkerScope.h"
+#include "nsGlobalWindow.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIDOMWindow.h"
 #include "nsIDocument.h"
 #include "nsXPCOM.h"
 #include "nsIXPConnect.h"
 #include "nsContentUtils.h"
 #include "nsError.h"
 #include "nsIScriptObjectPrincipal.h"
@@ -1576,21 +1577,95 @@ WebSocketImpl::Init(JSContext* aCx,
       // For workers, retrieve the URI from the WorkerPrivate
       principal = mWorkerPrivate->GetPrincipal();
     } else {
       // Check the principal's uri to determine if we were loaded from https.
       nsCOMPtr<nsIGlobalObject> globalObject(GetEntryGlobal());
       if (globalObject) {
         principal = globalObject->PrincipalOrNull();
       }
+
+      nsCOMPtr<nsPIDOMWindowInner> innerWindow;
+
+      while (true) {
+        bool isNullPrincipal = true;
+        if (principal) {
+          nsresult rv = principal->GetIsNullPrincipal(&isNullPrincipal);
+          if (NS_WARN_IF(NS_FAILED(rv))) {
+            aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+            return;
+          }
+        }
+
+        if (!isNullPrincipal) {
+          break;
+        }
+
+        if (!innerWindow) {
+          innerWindow = do_QueryInterface(globalObject);
+          if (NS_WARN_IF(!innerWindow)) {
+            aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+            return;
+          }
+        }
+
+        nsCOMPtr<nsPIDOMWindowOuter> parentWindow =
+          innerWindow->GetScriptableParent();
+        if (NS_WARN_IF(!parentWindow)) {
+          aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+          return;
+        }
+
+        nsCOMPtr<nsPIDOMWindowInner> currentInnerWindow =
+          parentWindow->GetCurrentInnerWindow();
+        if (NS_WARN_IF(!currentInnerWindow)) {
+          aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+          return;
+        }
+
+        // We are at the top. Let's see if we have an opener window.
+        if (innerWindow == currentInnerWindow) {
+          ErrorResult error;
+          parentWindow =
+            nsGlobalWindow::Cast(innerWindow)->GetOpenerWindow(error);
+          if (NS_WARN_IF(error.Failed())) {
+            error.SuppressException();
+            aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+            return;
+          }
+
+          if (!parentWindow) {
+            break;
+          }
+
+          currentInnerWindow = parentWindow->GetCurrentInnerWindow();
+          if (NS_WARN_IF(!currentInnerWindow)) {
+            aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+            return;
+          }
+
+          MOZ_ASSERT(currentInnerWindow != innerWindow);
+        }
+
+        innerWindow = currentInnerWindow;
+
+        nsCOMPtr<nsIDocument> document = innerWindow->GetExtantDoc();
+        if (NS_WARN_IF(!document)) {
+          aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+          return;
+        }
+
+        principal = document->NodePrincipal();
+      }
     }
 
     if (principal) {
       principal->GetURI(getter_AddRefs(originURI));
     }
+
     if (originURI) {
       bool originIsHttps = false;
       aRv = originURI->SchemeIs("https", &originIsHttps);
       if (NS_WARN_IF(aRv.Failed())) {
         return;
       }
       if (originIsHttps) {
         aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
--- a/dom/base/crashtests/637116.html
+++ b/dom/base/crashtests/637116.html
@@ -1,17 +1,17 @@
 <!DOCTYPE html>
 <html>
 
 <head>
 <script>
 
 function K(v) { return function() { return v; } }
 
-var errorProxy = Proxy.create({get: function() { throw new Error(); }});
+var errorProxy = new Proxy({}, {get: function() { throw new Error(); }});
 
 function boom()
 {
   var focused = document.createElementNS("http://www.w3.org/1999/xhtml", "input");
   document.body.appendChild(focused);
   var otherWin = window.open("data:text/html,1", "_blank", "width=200,height=200");
   try { otherWin.history.replaceState(errorProxy, "title", "replaceState.html"); } catch(e) {}
   focused.focus();
--- a/dom/base/crashtests/695867.html
+++ b/dom/base/crashtests/695867.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <script>
 
 var nodeList = document.documentElement.childNodes;
 nodeList.__proto__ = null;
-var p = Proxy.create({getPropertyDescriptor: function() {return nodeList}});
-p.x;
+var p = new Proxy({}, {getOwnPropertyDescriptor: function() {return nodeList}});
+Reflect.getOwnPropertyDescriptor(p, "x");
 
 </script>
deleted file mode 100644
--- a/dom/base/crashtests/708405-1.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-
-function boom()
-{
-  var a = document.getElementsByTagName("div");
-  a.__proto__ = Proxy.create({has: function() { throw new Error; }});
-  for (var p in a) {
-  }
-}
-
-</script>
-</head>
-
-<body onload="boom();"></body>
-</html>
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -138,17 +138,16 @@ load 693811-3.html
 load 693894.html
 load 695867.html
 load 697643.html
 load 698974-1.html
 load 700090-1.html
 load 700090-2.html
 load 700512.html
 load 706283-1.html
-load 708405-1.html
 load 709384.html
 load 709954.html
 load 713417-1.html
 load 713417-2.html
 load 715056.html
 load 729431-1.xhtml
 load 741163-1.html
 load 745495.html
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -878,20 +878,20 @@ public:
   uint32_t Length();
   already_AddRefed<nsPIDOMWindowOuter> GetTopOuter();
   already_AddRefed<nsPIDOMWindowOuter> GetTop(mozilla::ErrorResult& aError);
 
   nsresult GetPrompter(nsIPrompt** aPrompt) override;
 protected:
   explicit nsGlobalWindow(nsGlobalWindow *aOuterWindow);
   nsPIDOMWindowOuter* GetOpenerWindowOuter();
-  nsPIDOMWindowOuter* GetOpenerWindow(mozilla::ErrorResult& aError);
   // Initializes the mWasOffline member variable
   void InitWasOffline();
 public:
+  nsPIDOMWindowOuter* GetOpenerWindow(mozilla::ErrorResult& aError);
   void GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
                  mozilla::ErrorResult& aError);
   already_AddRefed<nsPIDOMWindowOuter> GetOpener() override;
   void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
                  mozilla::ErrorResult& aError);
   already_AddRefed<nsPIDOMWindowOuter> GetParentOuter();
   already_AddRefed<nsPIDOMWindowOuter> GetParent(mozilla::ErrorResult& aError);
   already_AddRefed<nsPIDOMWindowOuter> GetParent() override;
--- a/dom/bindings/crashtests/862610.html
+++ b/dom/bindings/crashtests/862610.html
@@ -1,14 +1,14 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta charset="UTF-8">
 <script>
-  HTMLElement.prototype.__proto__ = Proxy.create({}, {});
+  HTMLElement.prototype.__proto__ = new Proxy({}, {});
   try {
     window.Image;
   } finally {
     // Restore our prototype so the test harnesses can deal with us
     // We can't just assign to __proto__ because it lives on our proto chain
     // and we messed that up.
     var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
     desc.set.call(HTMLElement.prototype, Element.prototype);
--- a/dom/canvas/test/webgl-mochitest/test_webgl_disjoint_timer_query.html
+++ b/dom/canvas/test/webgl-mochitest/test_webgl_disjoint_timer_query.html
@@ -7,16 +7,21 @@
 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <script src="webgl-util.js"></script>
 </head>
 <body>
 <canvas id="c"></canvas>
 
 <script>
 
+function defer(f)
+{
+    setTimeout(f, 0);
+}
+
 function doTest() {
   var gl = WebGLUtil.getWebGL('c', true);
   var ext = gl.getExtension('EXT_disjoint_timer_query');
   if (!ext) {
     ok(true, "EXT_disjoint_timer_query may be unsupported.");
     SimpleTest.finish();
     return;
   }
@@ -31,34 +36,46 @@ function doTest() {
   ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, elapsedQuery);
   is(ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT), elapsedQuery,
      "Query is active after beginQueryEXT.");
   ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
   gl.flush();
 
   ok(!ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT),
      "Query is inactive after endQueryEXT.");
-  ok(ext.getQueryObjectEXT(elapsedQuery, ext.QUERY_RESULT_AVAILABLE_EXT),
-     "Time elapsed query is available immediately after flush.");
+
+  defer(function() {
+    ok(ext.getQueryObjectEXT(elapsedQuery, ext.QUERY_RESULT_AVAILABLE_EXT),
+       "Time elapsed query is available immediately after flush and event loop tick.");
 
-  ext.deleteQueryEXT(elapsedQuery);
-  ok(!ext.isQueryEXT(elapsedQuery), "Query is no longer valid after deletion.");
+    ext.deleteQueryEXT(elapsedQuery);
+    ok(!ext.isQueryEXT(elapsedQuery), "Query is no longer valid after deletion.");
+
+    ok(ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30,
+       "Time elapsed must be at least 30 bits to hold at least 1 second of timing.");
 
-  var timestampQuery = ext.createQueryEXT();
-  ext.queryCounterEXT(timestampQuery, ext.TIMESTAMP_EXT);
-  gl.flush();
-  ok(ext.getQueryObjectEXT(timestampQuery, ext.QUERY_RESULT_AVAILABLE_EXT),
-     "Timestamp query should be available immediately after flush.");
+    // D3D11 doesn't support TIMESTAMP_EXT so check for it before using it.
+    if (ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) > 0) {
+        var timestampQuery = ext.createQueryEXT();
+        ext.queryCounterEXT(timestampQuery, ext.TIMESTAMP_EXT);
+        gl.flush();
+        defer(function() {
+          ok(ext.getQueryObjectEXT(timestampQuery, ext.QUERY_RESULT_AVAILABLE_EXT),
+          "Timestamp query should be available immediately after flush and event loop tick.");
 
-  ok(ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30,
-     "Timestamp must be at least 30 bits to hold at least 1 second of timing.");
-  ok(ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30,
-     "Time elapsed must be at least 30 bits to hold at least 1 second of timing.");
+          ok(ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30,
+          "Time elapsed must be at least 30 bits to hold at least 1 second of timing.");
+
+          SimpleTest.finish();
 
-  SimpleTest.finish();
+          });
+    } else {
+      SimpleTest.finish();
+    }
+  });
 }
 
 SimpleTest.waitForExplicitFinish();
 
 SpecialPowers.pushPrefEnv({"set": [['webgl.enable-draft-extensions', true]]}, doTest);
 
 </script>
 </body>
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -4159,58 +4159,34 @@ EventStateManager::NotifyMouseOver(Widge
     wrapper->mLastOverFrame = nullptr;
     wrapper->mLastOverElement = nullptr;
   }
 
   // Turn recursion protection back off
   wrapper->mFirstOverEventElement = nullptr;
 }
 
-// Returns the center point of the window's inner content area.
-// This is in widget coordinates, i.e. relative to the widget's top
-// left corner, not in screen coordinates, the same units that
-// UIEvent::refPoint is in.
-//
-// XXX Hack alert: XXX
-// However, we do the computation in integer CSS pixels, NOT device pix,
-// in order to fudge around the one-pixel error in innerHeight in fullscreen
-// mode (see bug 799523 comment 35, and bug 729011). Using integer CSS pix
-// makes us throw away the fractional error that results, rather than having
-// it manifest as a potential one-device-pix discrepancy.
+// Returns the center point of the window's client area. This is
+// in widget coordinates, i.e. relative to the widget's top-left
+// corner, not in screen coordinates, the same units that UIEvent::
+// refpoint is in. It may not be the exact center of the window if
+// the platform requires rounding the coordinate.
 static LayoutDeviceIntPoint
-GetWindowInnerRectCenter(nsPIDOMWindowOuter* aWindow,
-                         nsIWidget* aWidget,
-                         nsPresContext* aContext)
+GetWindowClientRectCenter(nsIWidget* aWidget)
 {
-  NS_ENSURE_TRUE(aWindow && aWidget && aContext, LayoutDeviceIntPoint(0, 0));
-
-  nsGlobalWindow* window = nsGlobalWindow::Cast(aWindow);
-
-  float cssInnerX = window->GetMozInnerScreenXOuter();
-  int32_t innerX = int32_t(NS_round(cssInnerX));
-
-  float cssInnerY = window->GetMozInnerScreenYOuter();
-  int32_t innerY = int32_t(NS_round(cssInnerY));
-
-  ErrorResult dummy;
-  int32_t innerWidth = window->GetInnerWidthOuter(dummy);
-  dummy.SuppressException();
-
-  int32_t innerHeight = window->GetInnerHeightOuter(dummy);
-  dummy.SuppressException();
-
-  LayoutDeviceIntRect screen;
-  aWidget->GetScreenBounds(screen);
-
-  int32_t cssScreenX = aContext->DevPixelsToIntCSSPixels(screen.x);
-  int32_t cssScreenY = aContext->DevPixelsToIntCSSPixels(screen.y);
-
-  return LayoutDeviceIntPoint(
-    aContext->CSSPixelsToDevPixels(innerX - cssScreenX + innerWidth / 2),
-    aContext->CSSPixelsToDevPixels(innerY - cssScreenY + innerHeight / 2));
+  NS_ENSURE_TRUE(aWidget, LayoutDeviceIntPoint(0, 0));
+
+  LayoutDeviceIntRect rect;
+  aWidget->GetClientBounds(rect);
+  LayoutDeviceIntPoint point(rect.x + rect.width / 2,
+                             rect.y + rect.height / 2);
+  int32_t round = aWidget->RoundsWidgetCoordinatesTo();
+  point.x = point.x / round * round;
+  point.y = point.y / round * round;
+  return point - aWidget->WidgetToScreenOffset();
 }
 
 void
 EventStateManager::GeneratePointerEnterExit(EventMessage aMessage,
                                             WidgetMouseEvent* aEvent)
 {
   WidgetPointerEvent pointerEvent(*aEvent);
   pointerEvent.mMessage = aMessage;
@@ -4236,18 +4212,17 @@ EventStateManager::GenerateMouseEnterExi
       if (sIsPointerLocked && aMouseEvent->widget) {
         // The pointer is locked. If the pointer is not located at the center of
         // the window, dispatch a synthetic mousemove to return the pointer there.
         // Doing this between "real" pointer moves gives the impression that the
         // (locked) pointer can continue moving and won't stop at the screen
         // boundary. We cancel the synthetic event so that we don't end up
         // dispatching the centering move event to content.
         LayoutDeviceIntPoint center =
-          GetWindowInnerRectCenter(mDocument->GetWindow(), aMouseEvent->widget,
-                                   mPresContext);
+          GetWindowClientRectCenter(aMouseEvent->widget);
         aMouseEvent->lastRefPoint = center;
         if (aMouseEvent->refPoint != center) {
           // Mouse move doesn't finish at the center of the window. Dispatch a
           // synthetic native mouse event to move the pointer back to the center
           // of the window, to faciliate more movement. But first, record that
           // we've dispatched a synthetic mouse movement, so we can cancel it
           // in the other branch here.
           sSynthCenteringPoint = center;
@@ -4381,19 +4356,17 @@ EventStateManager::SetPointerLock(nsIWid
 
   if (sIsPointerLocked) {
     // Store the last known ref point so we can reposition the pointer after unlock.
     mPreLockPoint = sLastRefPoint;
 
     // Fire a synthetic mouse move to ensure event state is updated. We first
     // set the mouse to the center of the window, so that the mouse event
     // doesn't report any movement.
-    sLastRefPoint = GetWindowInnerRectCenter(aElement->OwnerDoc()->GetWindow(),
-                                             aWidget,
-                                             mPresContext);
+    sLastRefPoint = GetWindowClientRectCenter(aWidget);
     aWidget->SynthesizeNativeMouseMove(sLastRefPoint + aWidget->WidgetToScreenOffset(),
                                        nullptr);
 
     // Retarget all events to this element via capture.
     nsIPresShell::SetCapturingContent(aElement, CAPTURE_POINTERLOCK);
 
     // Suppress DnD
     if (dragService) {
@@ -5646,16 +5619,20 @@ EventStateManager::WheelPrefs::Init(Even
   mOverriddenActionsX[aIndex] = (actionOverrideX == -1)
                               ? static_cast<Action>(action)
                               : static_cast<Action>(actionOverrideX);
 }
 
 void
 EventStateManager::WheelPrefs::ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent)
 {
+  if (aEvent->customizedByUserPrefs) {
+    return;
+  }
+
   Index index = GetIndexFor(aEvent);
   Init(index);
 
   aEvent->deltaX *= mMultiplierX[index];
   aEvent->deltaY *= mMultiplierY[index];
   aEvent->deltaZ *= mMultiplierZ[index];
 
   // If the multiplier is 1.0 or -1.0, i.e., it doesn't change the absolute
--- a/dom/events/test/mochitest.ini
+++ b/dom/events/test/mochitest.ini
@@ -152,17 +152,17 @@ skip-if = toolkit == 'android' #CRASH_DU
 skip-if = buildapp == 'b2g' || e10s # b2g(5535 passed, 108 failed - more tests running than desktop) b2g-debug(5535 passed, 108 failed - more tests running than desktop) b2g-desktop(5535 passed, 108 failed - more tests running than desktop)
 [test_dblclick_explicit_original_target.html]
 [test_dom_keyboard_event.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dom_mouse_event.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dom_storage_event.html]
 [test_dom_wheel_event.html]
-skip-if = buildapp == 'b2g' || e10s # b2g(456 failed out of 19873, mousewheel test) b2g-debug(456 failed out of 19873, mousewheel test) b2g-desktop(456 failed out of 19873, mousewheel test)
+skip-if = buildapp == 'b2g' # b2g(456 failed out of 19873, mousewheel test) b2g-debug(456 failed out of 19873, mousewheel test) b2g-desktop(456 failed out of 19873, mousewheel test)
 [test_draggableprop.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dragstart.html]
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' # b2g(drag event, also fails on Android) b2g-debug(drag event, also fails on Android) b2g-desktop(drag event, also fails on Android)
 [test_error_events.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_eventctors.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -5776,19 +5776,19 @@ WorkerPrivate::ReportError(JSContext* aC
   JSExnType exnType = JSEXN_ERR;
   bool mutedError = aReport && aReport->isMuted;
 
   if (aReport) {
     // We want the same behavior here as xpc::ErrorReport::init here.
     xpc::ErrorReport::ErrorReportToMessageString(aReport, message);
 
     filename = NS_ConvertUTF8toUTF16(aReport->filename);
-    line = aReport->uclinebuf;
+    line.Assign(aReport->linebuf(), aReport->linebufLength());
     lineNumber = aReport->lineno;
-    columnNumber = aReport->uctokenptr - aReport->uclinebuf;
+    columnNumber = aReport->tokenOffset();
     flags = aReport->flags;
     errorNumber = aReport->errorNumber;
     MOZ_ASSERT(aReport->exnType >= JSEXN_NONE && aReport->exnType < JSEXN_LIMIT);
     exnType = JSExnType(aReport->exnType);
   }
   else {
     lineNumber = columnNumber = errorNumber = 0;
     flags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
--- a/editor/libeditor/PlaceholderTxn.cpp
+++ b/editor/libeditor/PlaceholderTxn.cpp
@@ -27,24 +27,24 @@ PlaceholderTxn::PlaceholderTxn() :  Edit
 PlaceholderTxn::~PlaceholderTxn()
 {
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(PlaceholderTxn)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PlaceholderTxn,
                                                 EditAggregateTxn)
-  tmp->mStartSel->DoUnlink();
-  tmp->mEndSel.DoUnlink();
+  ImplCycleCollectionUnlink(*tmp->mStartSel);
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mEndSel);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PlaceholderTxn,
                                                   EditAggregateTxn)
-  tmp->mStartSel->DoTraverse(cb);
-  tmp->mEndSel.DoTraverse(cb);
+  ImplCycleCollectionTraverse(cb, *tmp->mStartSel, "mStartSel", 0);
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndSel);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PlaceholderTxn)
   NS_INTERFACE_MAP_ENTRY(nsIAbsorbingTransaction)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_INHERITING(EditAggregateTxn)
 
 NS_IMPL_ADDREF_INHERITED(PlaceholderTxn, EditAggregateTxn)
--- a/editor/libeditor/nsEditor.cpp
+++ b/editor/libeditor/nsEditor.cpp
@@ -172,16 +172,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSpellChecker)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mTxnMgr)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mIMETextNode)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mActionListeners)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventListener)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mSavedSel);
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mRangeUpdater);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEditor)
  nsIDocument* currentDoc =
    tmp->mRootElement ? tmp->mRootElement->GetCurrentDoc() : nullptr;
  if (currentDoc &&
      nsCCUncollectableMarker::InGeneration(cb, currentDoc->GetMarkedCCGeneration())) {
    return NS_SUCCESS_INTERRUPTED_TRAVERSE;
@@ -190,16 +192,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineSpellChecker)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTxnMgr)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIMETextNode)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActionListeners)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorObservers)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocStateListeners)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventTarget)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventListener)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSavedSel);
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRangeUpdater);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsEditor)
  NS_INTERFACE_MAP_ENTRY(nsIPhonetic)
  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
  NS_INTERFACE_MAP_ENTRY(nsIEditorIMESupport)
  NS_INTERFACE_MAP_ENTRY(nsIEditor)
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditor)
--- a/editor/libeditor/nsHTMLEditRules.cpp
+++ b/editor/libeditor/nsHTMLEditRules.cpp
@@ -229,18 +229,23 @@ nsHTMLEditRules::~nsHTMLEditRules()
 }
 
 /********************************************************
  *  XPCOM Cruft
  ********************************************************/
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLEditRules, nsTextEditRules)
 NS_IMPL_RELEASE_INHERITED(nsHTMLEditRules, nsTextEditRules)
-NS_IMPL_QUERY_INTERFACE_INHERITED(nsHTMLEditRules, nsTextEditRules, nsIEditActionListener)
-
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLEditRules)
+  NS_INTERFACE_TABLE_INHERITED(nsHTMLEditRules, nsIEditActionListener)
+NS_INTERFACE_TABLE_TAIL_INHERITING(nsTextEditRules)
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(nsHTMLEditRules, nsTextEditRules,
+                                   mDocChangeRange, mUtilRange, mNewBlock,
+                                   mRangeItem)
 
 /********************************************************
  *  Public methods
  ********************************************************/
 
 NS_IMETHODIMP
 nsHTMLEditRules::Init(nsPlaintextEditor *aEditor)
 {
--- a/editor/libeditor/nsHTMLEditRules.h
+++ b/editor/libeditor/nsHTMLEditRules.h
@@ -59,16 +59,17 @@ struct StyleCache : public PropItem
 
 #define SIZE_STYLE_TABLE 19
 
 class nsHTMLEditRules : public nsTextEditRules, public nsIEditActionListener
 {
 public:
 
   NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLEditRules, nsTextEditRules)
 
   nsHTMLEditRules();
 
   // nsIEditRules methods
   NS_IMETHOD Init(nsPlaintextEditor *aEditor) override;
   NS_IMETHOD DetachEditor() override;
   NS_IMETHOD BeforeEdit(EditAction action,
                         nsIEditor::EDirection aDirection) override;
--- a/editor/libeditor/nsSelectionState.cpp
+++ b/editor/libeditor/nsSelectionState.cpp
@@ -31,31 +31,16 @@ using namespace mozilla::dom;
 nsSelectionState::nsSelectionState() : mArray(){}
 
 nsSelectionState::~nsSelectionState()
 {
   MakeEmpty();
 }
 
 void
-nsSelectionState::DoTraverse(nsCycleCollectionTraversalCallback &cb)
-{
-  for (uint32_t i = 0, iEnd = mArray.Length(); i < iEnd; ++i)
-  {
-    nsRangeStore* item = mArray[i];
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
-                                       "selection state mArray[i].startNode");
-    cb.NoteXPCOMChild(item->startNode);
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
-                                       "selection state mArray[i].endNode");
-    cb.NoteXPCOMChild(item->endNode);
-  }
-}
-
-void
 nsSelectionState::SaveSelection(Selection* aSel)
 {
   MOZ_ASSERT(aSel);
   int32_t arrayCount = mArray.Length();
   int32_t rangeCount = aSel->RangeCount();
 
   // if we need more items in the array, new them
   if (arrayCount < rangeCount) {
@@ -647,16 +632,20 @@ nsRangeUpdater::DidMoveNode(nsINode* aOl
 
 nsRangeStore::nsRangeStore()
 {
 }
 nsRangeStore::~nsRangeStore()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION(nsRangeStore, startNode, endNode)
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsRangeStore, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsRangeStore, Release)
+
 void
 nsRangeStore::StoreRange(nsRange* aRange)
 {
   MOZ_ASSERT(aRange);
   startNode = aRange->GetStartParent();
   startOffset = aRange->StartOffset();
   endNode = aRange->GetEndParent();
   endOffset = aRange->EndOffset();
--- a/editor/libeditor/nsSelectionState.h
+++ b/editor/libeditor/nsSelectionState.h
@@ -36,46 +36,64 @@ struct nsRangeStore final
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~nsRangeStore();
 
 public:
   void StoreRange(nsRange* aRange);
   already_AddRefed<nsRange> GetRange();
 
-  NS_INLINE_DECL_REFCOUNTING(nsRangeStore)
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsRangeStore)
+  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsRangeStore)
 
   nsCOMPtr<nsINode> startNode;
   int32_t           startOffset;
   nsCOMPtr<nsINode> endNode;
   int32_t           endOffset;
 };
 
 class nsSelectionState
 {
   public:
 
     nsSelectionState();
     ~nsSelectionState();
 
-    void DoTraverse(nsCycleCollectionTraversalCallback &cb);
-    void DoUnlink() { MakeEmpty(); }
-
     void     SaveSelection(mozilla::dom::Selection *aSel);
     nsresult RestoreSelection(mozilla::dom::Selection* aSel);
     bool     IsCollapsed();
     bool     IsEqual(nsSelectionState *aSelState);
     void     MakeEmpty();
     bool     IsEmpty();
-  protected:
+  private:
     nsTArray<RefPtr<nsRangeStore> > mArray;
 
     friend class nsRangeUpdater;
+    friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
+                                            nsSelectionState&,
+                                            const char*,
+                                            uint32_t);
+    friend void ImplCycleCollectionUnlink(nsSelectionState&);
 };
 
+inline void
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
+                            nsSelectionState& aField,
+                            const char* aName,
+                            uint32_t aFlags = 0)
+{
+  ImplCycleCollectionTraverse(aCallback, aField.mArray, aName, aFlags);
+}
+
+inline void
+ImplCycleCollectionUnlink(nsSelectionState& aField)
+{
+  ImplCycleCollectionUnlink(aField.mArray);
+}
+
 class nsRangeUpdater
 {
   public:
 
     nsRangeUpdater();
     ~nsRangeUpdater();
 
     void RegisterRangeItem(nsRangeStore *aRangeItem);
@@ -115,21 +133,41 @@ class nsRangeUpdater
     nsresult DidRemoveContainer(nsINode* aNode, nsINode* aParent,
                                 int32_t aOffset, uint32_t aNodeOrigLen);
     nsresult DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset, uint32_t aNodeOrigLen);
     nsresult WillInsertContainer();
     nsresult DidInsertContainer();
     void WillMoveNode();
     void DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
                      nsINode* aNewParent, int32_t aNewOffset);
-  protected:
+  private:
+    friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
+                                            nsRangeUpdater&,
+                                            const char*,
+                                            uint32_t);
+    friend void ImplCycleCollectionUnlink(nsRangeUpdater& aField);
+
     nsTArray<RefPtr<nsRangeStore> > mArray;
     bool mLock;
 };
 
+inline void
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
+                            nsRangeUpdater& aField,
+                            const char* aName,
+                            uint32_t aFlags = 0)
+{
+  ImplCycleCollectionTraverse(aCallback, aField.mArray, aName, aFlags);
+}
+
+inline void
+ImplCycleCollectionUnlink(nsRangeUpdater& aField)
+{
+  ImplCycleCollectionUnlink(aField.mArray);
+}
 
 /***************************************************************************
  * helper class for using nsSelectionState.  stack based class for doing
  * preservation of dom points across editor actions
  */
 
 class MOZ_STACK_CLASS nsAutoTrackDOMPoint
 {
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -827,18 +827,18 @@ frontend::CompileLazyFunction(JSContext*
 
     Rooted<JSScript*> script(cx, JSScript::Create(cx, enclosingScope, false, options,
                                                   sourceObject, lazy->begin(), lazy->end()));
     if (!script)
         return false;
 
     script->bindings = pn->pn_funbox->bindings;
 
-    if (lazy->usesArgumentsApplyAndThis())
-        script->setUsesArgumentsApplyAndThis();
+    if (lazy->isLikelyConstructorWrapper())
+        script->setLikelyConstructorWrapper();
     if (lazy->hasBeenCloned())
         script->setHasBeenCloned();
 
     /*
      * We just pass false for insideNonGlobalEval and insideEval, because we
      * don't actually know whether we are or not.  The only consumer of those
      * booleans is TryConvertFreeName, and it has special machinery to avoid
      * doing bad things when a lazy function is inside eval.
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -6427,18 +6427,18 @@ BytecodeEmitter::emitFunction(ParseNode*
                                  insideNonGlobalEval, lineNum, emitterMode);
             if (!bce2.init())
                 return false;
 
             /* We measured the max scope depth when we parsed the function. */
             if (!bce2.emitFunctionScript(pn->pn_body))
                 return false;
 
-            if (funbox->usesArguments && funbox->usesApply && funbox->usesThis)
-                script->setUsesArgumentsApplyAndThis();
+            if (funbox->isLikelyConstructorWrapper())
+                script->setLikelyConstructorWrapper();
         }
         if (outersc->isFunctionBox())
             outersc->asFunctionBox()->function()->nonLazyScript()->setHasInnerFunctions(true);
     } else {
         MOZ_ASSERT(IsAsmJSModule(fun));
     }
 
     /* Make the function object a literal in the outer script's pool. */
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -783,16 +783,17 @@ FunctionBox::FunctionBox(ExclusiveContex
     inGenexpLambda(false),
     hasDestructuringArgs(false),
     useAsm(false),
     insideUseAsm(outerpc && outerpc->useAsmOrInsideUseAsm()),
     wasEmitted(false),
     usesArguments(false),
     usesApply(false),
     usesThis(false),
+    usesReturn(false),
     funCxFlags()
 {
     // Functions created at parse time may be set singleton after parsing and
     // baked into JIT code, so they must be allocated tenured. They are held by
     // the JSScript so cannot be collected during a minor GC anyway.
     MOZ_ASSERT(fun->isTenured());
 }
 
@@ -2879,18 +2880,18 @@ Parser<SyntaxParseHandler>::finishFuncti
 
     HeapPtrFunction* innerFunctions = lazy->innerFunctions();
     for (size_t i = 0; i < numInnerFunctions; i++)
         innerFunctions[i].init(pc->innerFunctions[i]);
 
     if (pc->sc->strict())
         lazy->setStrict();
     lazy->setGeneratorKind(funbox->generatorKind());
-    if (funbox->usesArguments && funbox->usesApply && funbox->usesThis)
-        lazy->setUsesArgumentsApplyAndThis();
+    if (funbox->isLikelyConstructorWrapper())
+        lazy->setLikelyConstructorWrapper();
     if (funbox->isDerivedClassConstructor())
         lazy->setIsDerivedClassConstructor();
     if (funbox->needsHomeObject())
         lazy->setNeedsHomeObject();
     PropagateTransitiveParseFlags(funbox, lazy);
 
     fun->initLazyScript(lazy);
     return true;
@@ -6504,16 +6505,17 @@ Parser<ParseHandler>::breakStatement(Yie
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::returnStatement(YieldHandling yieldHandling)
 {
     MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_RETURN));
     uint32_t begin = pos().begin;
 
     MOZ_ASSERT(pc->sc->isFunctionBox());
+    pc->sc->asFunctionBox()->usesReturn = true;
 
     // Parse an optional operand.
     //
     // This is ugly, but we don't want to require a semicolon.
     Node exprNode;
     TokenKind tt = TOK_EOF;
     if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
         return null();
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -325,29 +325,34 @@ class FunctionBox : public ObjectBox, pu
     bool            useAsm:1;               /* see useAsmOrInsideUseAsm */
     bool            insideUseAsm:1;         /* see useAsmOrInsideUseAsm */
     bool            wasEmitted:1;           /* Bytecode has been emitted for this function. */
 
     // Fields for use in heuristics.
     bool            usesArguments:1;  /* contains a free use of 'arguments' */
     bool            usesApply:1;      /* contains an f.apply() call */
     bool            usesThis:1;       /* contains 'this' */
+    bool            usesReturn:1;     /* contains a 'return' statement */
 
     FunctionContextFlags funCxFlags;
 
     template <typename ParseHandler>
     FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun,
                 JSObject* enclosingStaticScope, ParseContext<ParseHandler>* pc,
                 Directives directives, bool extraWarnings, GeneratorKind generatorKind);
 
     ObjectBox* toObjectBox() override { return this; }
     JSFunction* function() const { return &object->as<JSFunction>(); }
     JSObject* staticScope() const override { return function(); }
     JSObject* enclosingStaticScope() const { return enclosingStaticScope_; }
 
+    bool isLikelyConstructorWrapper() const {
+        return usesArguments && usesApply && usesThis && !usesReturn;
+    }
+
     GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
     bool isGenerator() const { return generatorKind() != NotGenerator; }
     bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
     bool isStarGenerator() const { return generatorKind() == StarGenerator; }
     bool isArrow() const { return function()->isArrow(); }
 
     void setGeneratorKind(GeneratorKind kind) {
         // A generator kind can be set at initialization, or when "yield" is
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -579,18 +579,17 @@ CompileError::throwError(JSContext* cx)
     // returns false, the top-level reporter will eventually receive the
     // uncaught exception report.
     if (!ErrorToException(cx, message, &report, nullptr, nullptr))
         CallErrorReporter(cx, message, &report);
 }
 
 CompileError::~CompileError()
 {
-    js_free((void*)report.uclinebuf);
-    js_free((void*)report.linebuf);
+    js_free((void*)report.linebuf());
     js_free((void*)report.ucmessage);
     js_free(message);
     message = nullptr;
 
     if (report.messageArgs) {
         if (argumentsType == ArgumentsAreASCII) {
             unsigned i = 0;
             while (report.messageArgs[i])
@@ -686,32 +685,27 @@ TokenStream::reportCompileErrorNumberVA(
         // windowRadius after offset.
         size_t windowEnd = userbuf.findEOLMax(offset, windowRadius);
         size_t windowLength = windowEnd - windowStart;
         MOZ_ASSERT(windowLength <= windowRadius * 2);
 
         // Create the windowed strings.
         StringBuffer windowBuf(cx);
         if (!windowBuf.append(userbuf.rawCharPtrAt(windowStart), windowLength) ||
-            !windowBuf.append((char16_t)0))
+            !windowBuf.append('\0'))
+        {
+            return false;
+        }
+
+        // The window into the offending source line, without final \n.
+        UniqueTwoByteChars linebuf(windowBuf.stealChars());
+        if (!linebuf)
             return false;
 
-        // Unicode and char versions of the window into the offending source
-        // line, without final \n.
-        err.report.uclinebuf = windowBuf.stealChars();
-        if (!err.report.uclinebuf)
-            return false;
-
-        mozilla::Range<const char16_t> tbchars(err.report.uclinebuf, windowLength);
-        err.report.linebuf = JS::LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
-        if (!err.report.linebuf)
-            return false;
-
-        err.report.tokenptr = err.report.linebuf + (offset - windowStart);
-        err.report.uctokenptr = err.report.uclinebuf + (offset - windowStart);
+        err.report.initLinebuf(linebuf.release(), windowLength, offset - windowStart);
     }
 
     if (cx->isJSContext())
         err.throwError(cx->asJSContext());
 
     return warning;
 }
 
deleted file mode 100644
--- a/js/src/jit-test/tests/TypedObject/fuzz3.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// |jit-test| error:RangeError;
-load(libdir + "immutable-prototype.js");
-
-if (!this.hasOwnProperty("TypedObject"))
-  throw new RangeError();
-
-if (globalPrototypeChainIsMutable())
-  this.__proto__ =  Proxy.create({});
-
-new TypedObject.StructType;
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug568281.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// |jit-test| error:TypeError
-
-// Binary: cache/js-dbg-64-9ca0a738a8ad-linux
-// Flags:
-//
-__defineSetter__("x", Array.reduce)
-x = Proxy.create(function() {},
-this.watch("x",
-function() {
-  yield
-}))
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug568855.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// Binary: cache/js-dbg-32-fadb38356e0f-linux
-// Flags: -j
-//
-load(libdir + "immutable-prototype.js");
-
-if (globalPrototypeChainIsMutable())
-{
-  this.__proto__ = Proxy.create({
-      has:function(){return false},
-      set:function(){}
-  });
-}
-
-(function(){
-  eval("(function(){ for(var j=0;j<6;++j) if(j%2==1) p=0; })")();
-})()
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug578015.js
+++ /dev/null
@@ -1,14 +0,0 @@
-// Binary: cache/js-dbg-64-60c111fc0d4b-linux
-// Flags:
-//
-(function () {
-    x = Proxy.createFunction((function () {
-        return {
-            getOwnPropertyDescriptor: function () {
-                return this
-            },
-            get: undefined
-        }
-    })(), Object.getOwnPropertyDescriptor)
-})()
-x(x)
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug580200.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// |jit-test| error:TypeError
-
-// Binary: cache/js-dbg-64-c271aa43c7ab-linux
-// Flags:
-//
-(function () {
-    x = Proxy.create((function () {
-        return {
-            enumerateOwn: function () Object.getOwnPropertyDescriptor
-        }
-    })(), [])
-})()(uneval(this))
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug586559.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// |jit-test| error:TypeError
-
-// Binary: cache/js-dbg-32-805fd625e65f-linux
-// Flags: -j
-//
-x = Proxy.create((function () {
-    return {
-        get: function () {}
-    }
-}()), Object.e)
-Function("\
-  for(var a = 0; a < 2; ++a) {\
-    if (a == 0) {}\
-    else {\
-      x > x\
-    }\
-  }\
-")()
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug587433.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// |jit-test| error:TypeError
-
-// Binary: cache/js-dbg-32-89b775191b9d-linux
-// Flags: -j
-//
-x = Proxy.create(function() {
-  return {
-    get: function() {}
-  };
-} ());
-for (var a = 0; a < 6; ++a) {
-  if (a == 3) {
-    x > ""
-  }
-}
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug589103.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// |jit-test| error:InternalError
-
-// Binary: cache/js-dbg-64-b22e82ce2364-linux
-// Flags:
-//
-load(libdir + "immutable-prototype.js");
-
-if (globalPrototypeChainIsMutable())
-  __proto__ = Proxy.create(this, "");
-
-throw new InternalError("fallback");
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug592226.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// |jit-test| error:TypeError
-
-// Binary: cache/js-dbg-64-e8ee411dca70-linux
-// Flags:
-//
-x = Proxy.create((function () {
-    return {
-        get: Object.create
-    }
-})([]), "")
-try {
-    (function () {
-        for each(l in [0]) {
-            print(x)
-        }
-    })()
-} catch (e) {}
-gc()
-for each(let a in [0]) {
-    print(x)
-}
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug609287.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// |jit-test| error:TypeError
-
-// Binary: cache/js-dbg-32-7ec0a71652a6-linux
-// Flags:
-//
-f = eval("\
-  (function() {\
-    __proto__ = \
-    Proxy.createFunction((\
-    function() {\
-      return {\
-        has: new ArrayBuffer,\
-      }\
-    })\
-    (\"\"), \
-    JSON.parse\
-    )\
-  })\
-")()
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug610088.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// Binary: cache/js-dbg-64-7ef107ab081e-linux
-// Flags:
-//
-var sandbox = evalcx("");
-function e(code) { try { evalcx(code, sandbox); } catch(e) { } }
-e("let x;");
-e("Object.seal(this);");
-e("x=Proxy.createFunction({keys:Object.getPrototypeOf},function(){})");
-e("const y;");
-
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug664951.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// |jit-test| error:TypeError
-
-// Binary: cache/js-dbg-64-66c8ad02543b-linux
-// Flags:
-//
-var handler = { fix: function() { return []; } };
-var p = Proxy.createFunction(handler, function(){}, function(){});
-Proxy.fix(p);
-new p();
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug675520.js
+++ /dev/null
@@ -1,6 +0,0 @@
-// Binary: cache/js-dbg-64-6ca8580eb84f-linux
-// Flags:
-//
-var handler = {iterate: function() { return Iterator.prototype; }};
-var proxy = Proxy.create(handler);
-for (var p in proxy) { }
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug698150.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// Binary: cache/js-dbg-64-b01eb1ba58ce-linux
-// Flags: -m -n
-//
-
-gczeal(2);
-var g1 = newGlobal('same-compartment');
-var proxyStr = "Proxy.create(                                    "+
-"  { getOwnPropertyDescriptor: function() assertEq(true,false),  "+
-"    fix: function() assertEq(true,false), },                    "+
-"  Object.prototype                                              "+
-");                                                              ";
-var proxy1 = g1.eval(proxyStr);
--- a/js/src/jit-test/tests/auto-regress/bug727330.js
+++ b/js/src/jit-test/tests/auto-regress/bug727330.js
@@ -1,9 +1,9 @@
 // |jit-test| error:TypeError
 
 // Binary: cache/js-dbg-64-ff51ddfdf5d1-linux
 // Flags:
 //
 var a = [];
 for (var i = 0; i < 200; ++i) a.push({});
-var p = Proxy.create({fix: function() { return a; }});
+var p = new Proxy({}, {preventExtensions() { return false; }});
 Object.preventExtensions(p);
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug759306.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// |jit-test| error:TypeError
-
-// Binary: cache/js-dbg-32-4ce3983a43f4-linux
-// Flags:
-//
-
-function assertEq(setter) {
-        if (setter > 10)
-            return {assertEq: 3.3};
-        return {__proto__: assertEq(setter + 1)};
-    }
-function testX() {
-  var x = 2;
-  var local0 = x;
-  return { local0: local0 };
-}
-var resultsX = testX();
-assertEq(resultsX.local0, 2);
-gczeal(2);
-assertEq(new (Proxy.createFunction({}, function(){}, function(){})), undefined);
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug811612.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// |jit-test| error:TypeError
-
-// Binary: cache/js-dbg-64-4e9567eeb09e-linux
-// Flags:
-//
-evaluate({
-    e: [].some(Proxy.create(function() {}), "")
-})
deleted file mode 100644
--- a/js/src/jit-test/tests/baseline/bug1097585.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// |jit-test| error:TypeError
-x = Proxy.createFunction(function() {}, function() {})
-function f() {
-    x = Proxy.create(function() {}, x())
-}
-f()
-f()
deleted file mode 100644
--- a/js/src/jit-test/tests/baseline/bug842319.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// |jit-test| error: TypeError
-Array.prototype.__proto__ = Proxy.create({
-    getPropertyDescriptor: function(name) {
-	return 0;
-    },
-}, null);
-var statusitems = [];
-statusitems[0] = '';
deleted file mode 100644
--- a/js/src/jit-test/tests/baseline/bug844464.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// |jit-test| error: TypeError
-Object = function () {};
-var p = Proxy.create({});
-Object.prototype.__proto__ = p;
-function newFunc(x) { new Function(x)(); };
-newFunc('\
-function f(v, value) {\
-    "failed: " + v + " " + value\
-}\
-f({}, false);\
-f(Object.prototype, false);\
-');
--- a/js/src/jit-test/tests/baseline/bug881461.js
+++ b/js/src/jit-test/tests/baseline/bug881461.js
@@ -1,2 +1,2 @@
-z = Proxy.create({}, (function(){}));
+z = new Proxy({__proto__: (function(){})}, {});
 ({__proto__: z, set c(a) {}});
--- a/js/src/jit-test/tests/basic/bug1054243.js
+++ b/js/src/jit-test/tests/basic/bug1054243.js
@@ -1,3 +1,3 @@
 // |jit-test| error: uncaught exception
-var prox = Proxy.create({getOwnPropertyDescriptor: function() { throw prox; }});
+var prox = new Proxy({}, {getOwnPropertyDescriptor: function() { throw prox; }});
 Object.prototype.__lookupGetter__.call(prox, 'q');
--- a/js/src/jit-test/tests/basic/bug1085464.js
+++ b/js/src/jit-test/tests/basic/bug1085464.js
@@ -1,13 +1,13 @@
 function *f() {
-    var o = Proxy.createFunction({
+    var o = new Proxy({}, {
         get: function() { assertEq(0, 1); },
         has: function() { assertEq(0, 2); }
-    }, function() {});
+    });
 
     with (o) {
         yield 1;
         with ({}) {
             yield 2;
         }
     }
     with ({".generator": 100}) {
--- a/js/src/jit-test/tests/basic/bug1113980.js
+++ b/js/src/jit-test/tests/basic/bug1113980.js
@@ -1,9 +1,9 @@
-var p = Proxy.create({
+var p = new Proxy({}, {
     getOwnPropertyDescriptor: function() {
         return {value: 1, configurable: true, writable: true};
     },
     defineProperty: function() {
     }
 }, null);
 
 var o = Object.create(p);
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/bug1172503.js
+++ /dev/null
@@ -1,13 +0,0 @@
-// |jit-test| error: m is not defined
-load(libdir + "immutable-prototype.js");
-
-if (globalPrototypeChainIsMutable()) {
-  this.__proto__ = Proxy.create({
-    has:function(){
-      try {
-        aa0 = Function(undefined);
-      } catch (aa) {}
-    }
-  });
-}
-m();
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/bug602088.js
+++ /dev/null
@@ -1,6 +0,0 @@
-// |jit-test| error: TypeError
-/* vim: set ts=8 sts=4 et sw=4 tw=99: */
-
-var p = Proxy.createFunction({}, function(x, y) { undefined.x(); });
-print(new p(1, 2));
-
--- a/js/src/jit-test/tests/basic/bug641525.js
+++ b/js/src/jit-test/tests/basic/bug641525.js
@@ -1,10 +1,10 @@
 
-var o2 = Proxy.create({});
+var o2 = new Proxy({}, {});
 function f1() {}
 function f2() {}
 function f4(o) {
     var key = Object.getOwnPropertyNames(o)[18];
     o4 = o[key];
     o.prototype = {};
 }
 f4(f1);
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/bug657227.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var obj;
-var counter = 0;
-var p = Proxy.create({
-    has : function(id) {
-	if (id == 'xyz') {
-	    ++counter;
-	    if (counter == 7) {
-		obj.__proto__ = null;
-	    }
-	    return true;
-	}
-	return false;
-    },
-    get : function(id) {
-	if (id == 'xyz')
-	    return 10;
-    }
-});
-
-function test()
-{
-    Object.prototype.__proto__ = null;
-    obj = { xyz: 1};
-    var n = 0;
-    for (var i = 0; i != 100; ++i) {
-	var s = obj.xyz;
-	if (s)
-	    ++n;
-	if (i == 10) {
-	    delete obj.xyz;
-	    Object.prototype.__proto__ = p;
-	}
-
-    }
-}
-
-try {
-    test();
-} catch (e) {}
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/bug737251.js
+++ /dev/null
@@ -1,10 +0,0 @@
-a = {}
-a.getOwnPropertyDescriptor = Array;
-b = Proxy.create(a)
-for (x in this)
-try {
-  (function() {
-    "use strict";
-    b[2] = x // don't assert
-  })()
-} catch (e) {}
--- a/js/src/jit-test/tests/basic/bug763440.js
+++ b/js/src/jit-test/tests/basic/bug763440.js
@@ -5,17 +5,17 @@ var actual = '';
 gcPreserveCode()
 function TestCase(n, d, e, a) {
   this.name=n;
 }
 function reportCompare (expected, actual, description) {
   new TestCase
 }
 reportCompare(true, eval++, "Dummy description.");
-var p = Proxy.create({
+var p = new Proxy({}, {
     has : function(id) {},
     set : function() {}
 });
 if (globalPrototypeChainIsMutable())
     Object.prototype.__proto__ = p;
 new TestCase;
 var expect = '';
 reportCompare(expect, actual, summary);
--- a/js/src/jit-test/tests/basic/bug767273.js
+++ b/js/src/jit-test/tests/basic/bug767273.js
@@ -1,7 +1,7 @@
-var prox = Proxy.create({
+var prox = new Proxy({}, {
   getOwnPropertyDescriptor: function() { return undefined; },
   has:                      function() { return true; },
 });
 
 // Don't crash.
 newGlobal().__lookupSetter__.call(prox, "e");
--- a/js/src/jit-test/tests/basic/bug787847.js
+++ b/js/src/jit-test/tests/basic/bug787847.js
@@ -1,17 +1,17 @@
 var g = true;
 
-function getown(name)
+function get(name)
 {
     if (g)
-	return { value: 8, enumerable: true, writable: false, configurable: true };
+	   return 8;
 }
 
-var p = Proxy.create( { getPropertyDescriptor: getown } );
+var p = new Proxy({}, { get: get } );
 var o2 = Object.create(p);
 
 function test(x, expected) {
     for (var i=0; i<3; i++) {
 	var v = x.hello;
 	if (g) assertEq(v, 8);
     }
 }
--- a/js/src/jit-test/tests/basic/bug807623.js
+++ b/js/src/jit-test/tests/basic/bug807623.js
@@ -1,12 +1,17 @@
-var objectProxy = Proxy.create({});
-var functionProxy = Proxy.createFunction({}, function() {}, function() {});
+var objectProxy = new Proxy({}, {});
+var functionProxy = new Proxy(function() {}, {});
 
 assertEq(Object.prototype.toString.call(objectProxy), '[object Object]');
 assertEq(Object.prototype.toString.call(functionProxy), '[object Function]');
-assertEq(Function.prototype.toString.call(functionProxy), 'function () {}');
+try {
+  Function.prototype.toString.call(functionProxy);
+  assertEq(true, false);
+} catch (e) {
+  assertEq(!!/incompatible/.exec(e), true);
+}
 try {
   Function.prototype.toString.call(objectProxy);
   assertEq(true, false);
 } catch (e) {
   assertEq(!!/incompatible/.exec(e), true);
 }
--- a/js/src/jit-test/tests/basic/bug830049.js
+++ b/js/src/jit-test/tests/basic/bug830049.js
@@ -1,21 +1,12 @@
 // |jit-test| error: TypeError
 load(libdir + "immutable-prototype.js");
 
-p = Proxy.create({
-  has: function() { return function r() { return (s += ''); } },
-  get: function() { throw new TypeError("hit get"); }
-});
-
-if (globalPrototypeChainIsMutable()) {
-    Object.prototype.__proto__ = p;
-} else {
-    Object.defineProperty(Object.prototype, "name",
-                          { set(v) { throw new TypeError("hit name"); },
-                            enumerable: true,
-                            configurable: true });
-}
+Object.defineProperty(Object.prototype, "name",
+                      { set(v) { throw new TypeError("hit name"); },
+                        enumerable: true,
+                        configurable: true });
 
 function TestCase(n) {
     this.name = n;
 }
 new TestCase();
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/bug836601.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// |jit-test| error: InternalError
-let k
-Proxy.createFunction(function() {
-    return {
-        get: (n) => new Uint32Array(n)
-    }
-}(), decodeURIComponent) & k
-
--- a/js/src/jit-test/tests/basic/bug842940.js
+++ b/js/src/jit-test/tests/basic/bug842940.js
@@ -1,1 +1,1 @@
-try { for (let v of wrapWithProto(Proxy.create({}), [])) { } } catch (e) {}
+try { for (let v of wrapWithProto(new Proxy({}, {}), [])) { } } catch (e) {}
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/proxy-assign-inherited.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// When we assign to a property that a proxy claims is inherited, the
-// defineProperty handler call to create the new own property should get
-// the newly assigned value.
-
-var hits;
-var handlers = {
-  getOwnPropertyDescriptor: function(name) {
-    return undefined;
-  },
-  getPropertyDescriptor: function(name) {
-    return { value:42, writable:true, enumerable:true, configurable:true };
-  },
-  defineProperty: function(name, descriptor) {
-    hits++;
-    assertEq(name, 'x');
-    assertEq(descriptor.value, 43);
-  }
-};
-hits = 0;
-Proxy.create(handlers).x = 43;
-assertEq(hits, 1);
\ No newline at end of file
--- a/js/src/jit-test/tests/basic/splice-check-steps.js
+++ b/js/src/jit-test/tests/basic/splice-check-steps.js
@@ -1,96 +1,51 @@
 /*
  * Check the order of splice's internal operations, because the ordering is
  * visible externally.
  */
 
-function handlerMaker(obj, expected_exceptions) {
+function handlerMaker(expected_exceptions) {
   var order = [];
   function note(trap, name)
   {
       order.push(trap + '-' + name);
       if (expected_exceptions[trap] === name) {
           throw ("fail");
       }
   }
 
   return [{
     /* this is the only trap we care about */
-    delete: function(name) {
+    deleteProperty: function(target, name) {
       note("del", name);
-      return delete obj[name];
-    },
-
-    // Fundamental traps
-    getOwnPropertyDescriptor: function(name) {
-      var desc = Object.getOwnPropertyDescriptor(obj, name);
-      // a trapping proxy's properties must always be configurable
-      if (desc !== undefined)
-        desc.configurable = true;
-      return desc;
+      return Reflect.deleteProperty(target, name);
     },
-    getPropertyDescriptor:  function(name) {
-      var desc = Object.getPropertyDescriptor(obj, name); // not in ES5
-      // a trapping proxy's properties must always be configurable
-      if (desc !== undefined)
-        desc.configurable = true;
-      return desc;
-    },
-    getOwnPropertyNames: function() {
-      return Object.getOwnPropertyNames(obj);
-    },
-    getPropertyNames: function() {
-      return Object.getPropertyNames(obj);                // not in ES5
-    },
-    defineProperty: function(name, desc) {
-      note("def", name);
-      Object.defineProperty(obj, name, desc);
+    // derived traps
+    has:          function(target, name) {
+      note("has", name);
+      return name in target;
     },
-    fix:          function() {
-      if (Object.isFrozen(obj)) {
-        return Object.getOwnPropertyNames(obj).map(function(name) {
-          return Object.getOwnPropertyDescriptor(obj, name);
-        });
-      }
-      // As long as obj is not frozen, the proxy won't allow itself to be fixed
-      return undefined; // will cause a TypeError to be thrown
-    },
-
-    // derived traps
-    has:          function(name) {
-      note("has", name);
-      return name in obj;
+    get:          function(target, name, receiver) {
+      note("get", name);
+      return Reflect.get(target, name, receiver);
     },
-    hasOwn:       function(name) { return Object.prototype.hasOwnProperty.call(obj, name); },
-    get:          function(receiver, name) {
-      note("get", name);
-      return obj[name];
-    },
-    set:          function(receiver, name, val) {
+    set:          function(target, name, value, receiver) {
       note("set", name);
-      obj[name] = val;
-      return true; // bad behavior when set fails in non-strict mode
+      return Reflect.set(target, name, value, receiver);
     },
-    enumerate:    function() {
-      var result = [];
-      for (name in obj)
-        result.push(name);
-      return result;
-    },
-    keys: function() { return Object.keys(obj) }
   }, order];
 }
 
 // arr: the array to splice
 // expected_order: the expected order of operations on arr, stringified
 function check_splice_proxy(arr, expected_order, expected_exceptions, expected_array, expected_result) {
     print (arr);
-    var [handler, store] = handlerMaker(arr, expected_exceptions);
-    var proxy = Proxy.create(handler);
+    var [handler, store] = handlerMaker(expected_exceptions);
+    var proxy = new Proxy(arr, handler);
 
     try {
         var args = Array.prototype.slice.call(arguments, 5);
         var result = Array.prototype.splice.apply(proxy, args);
         assertEq(Object.keys(expected_exceptions).length, 0);
     } catch (e) {
         assertEq(Object.keys(expected_exceptions).length > 0, true);
     }
--- a/js/src/jit-test/tests/basic/testBug579602.js
+++ b/js/src/jit-test/tests/basic/testBug579602.js
@@ -1,20 +1,20 @@
 // don't panic
 
 f = function() {
   x = yield
 }
 rv = f()
 for (a in rv) (function() {})
-x = Proxy.create((function() {
+x = new Proxy({}, (function() {
   return {
     defineProperty: gc
   }
-})(), x)
+})());
 with({
   d: (({
     x: Object.defineProperty(x, "", ({
       set: Array.e
     }))
   }))
 }) {}
 
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/testBug660734.js
+++ /dev/null
@@ -1,6 +0,0 @@
-if (Proxy.fix) {
-    var handler = { fix: function() { return []; } };
-    var p = Proxy.createFunction(handler, function(){}, function(){});
-    Proxy.fix(p);
-    new p();
-}
--- a/js/src/jit-test/tests/basic/testBug676486.js
+++ b/js/src/jit-test/tests/basic/testBug676486.js
@@ -1,10 +1,8 @@
-var proxy = Proxy.createFunction(
-    {},
-    function() {
+var proxy = new Proxy(function() {
         return (function () { eval("foo") })();
-    });
+    }, {});
 
 try {
     new proxy();
 } catch (e) {
 }
--- a/js/src/jit-test/tests/basic/testBug762432.js
+++ b/js/src/jit-test/tests/basic/testBug762432.js
@@ -1,21 +1,15 @@
 function getter() { return 1; }
 function setter() { }
-function getDescriptor(name) {
+function getDescriptor(target, name) {
   if (name != 'prop')
     throw "Unknown property: " + name;
   return { configurable: true, enumerable: true, get: getter, set: setter };
 }
-function getNames() { return ['prop']; }
 var handler = {
   getOwnPropertyDescriptor: getDescriptor,
-  getPropertyDescriptor: getDescriptor,
-  getOwnPropertyNames: getNames,
-  getPropertyNames: getNames,
-  defineProperty: function() {},
-  delete: function() {}
 };
 
 // Make sure that __lookup{Getter,Setter}__ works on proxies.
-var proxy = Proxy.create(handler);
+var proxy = new Proxy({}, handler);
 assertEq(Object.prototype.__lookupGetter__.call(proxy, 'prop'), getter);
 assertEq(Object.prototype.__lookupSetter__.call(proxy, 'prop'), setter);
--- a/js/src/jit-test/tests/basic/testBug770407.js
+++ b/js/src/jit-test/tests/basic/testBug770407.js
@@ -1,4 +1,4 @@
 // |jit-test| error:TypeError
 var otherGlobal = newGlobal();
-var proxy = otherGlobal.Proxy.create({}, {});
+var proxy = new (otherGlobal.Proxy)({}, {});
 Int8Array.set(proxy);
--- a/js/src/jit-test/tests/basic/testCrossCompartmentTransparency.js
+++ b/js/src/jit-test/tests/basic/testCrossCompartmentTransparency.js
@@ -1,22 +1,20 @@
 // |jit-test| error: done
 
 var g1 = newGlobal('same-compartment');
 var g2 = newGlobal();
-var proxyStr = "Proxy.create(                              "+
+var proxyStr = "new Proxy({},                              "+
 "  { getOwnPropertyDescriptor: () =>assertEq(true,false),  "+
-"    getPropertyDescriptor: () =>assertEq(true,false),     "+
-"    getOwnPropertyNames: () =>assertEq(true,false),       "+
-"    getPropertyNames: () =>assertEq(true,false),          "+
+"    ownKeys: () =>assertEq(true,false),                   "+
 "    defineProperty: () =>assertEq(true,false),            "+
-"    delete: () =>assertEq(true,false),                    "+
-"    fix: () =>assertEq(true,false), },                    "+
-"  Object.prototype                                        "+
-");                                                        ";
+"    deleteProperty: () =>assertEq(true,false),            "+
+"    get: () =>assertEq(true,false),                       "+
+"    set: () =>assertEq(true,false),                       "+
+"});                                                       ";
 var proxy1 = g1.eval(proxyStr);
 var proxy2 = g2.eval(proxyStr);
 
 function test(str, f, isGeneric = false) {
     "use strict";
 
     var x = f(eval(str));
     assertEq(x, f(g1.eval(str)));
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/testProxyConstructors.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// |jit-test| error: ExitCleanly
-
-var handler = { getPropertyDescriptor() { return undefined; } }
-
-assertEq((new (Proxy.createFunction(handler,
-                                    function(){ this.x = 1 },
-                                    function(){ this.x = 2 }))).x, 2);
-// proxies can return the callee
-var x = Proxy.createFunction(handler, function (q) { return q; });
-assertEq(new x(x), x);
-try {
-    var x = (Proxy.createFunction(handler, "".indexOf));
-    new x;
-    throw "Should not be reached"
-}
-catch (e) {
-    assertEq(String(e.message).indexOf('is not a constructor') === -1, false);
-}
-throw "ExitCleanly"
--- a/js/src/jit-test/tests/basic/testProxyDefinePropertyWithMissingSetter.js
+++ b/js/src/jit-test/tests/basic/testProxyDefinePropertyWithMissingSetter.js
@@ -1,21 +1,20 @@
 // throw, don't crash
 
 var actual = "";
 
 try {
 
-(x = Proxy.createFunction((function() {
-  return {
-    defineProperty: function(name, desc) {
+var x = new Proxy({}, {
+    defineProperty: function(target, name, desc) {
       Object.defineProperty(x, name, desc)
     },
-  }
-})(), (eval)));
+});
+
 Object.defineProperty(x, "", ({
   get: function() {}
 }))
 
 } catch (e) {
     actual = '' + e;
 }
 
--- a/js/src/jit-test/tests/debug/Object-apply-04.js
+++ b/js/src/jit-test/tests/debug/Object-apply-04.js
@@ -6,10 +6,10 @@ var dbg = Debugger(g);
 var hits = 0;
 dbg.onDebuggerStatement = function (frame) {
     var proxy = frame.arguments[0];
     assertEq(proxy.name, undefined);
     assertEq(proxy.apply(null, [33]).return, 34);
     assertEq(proxy.call(null, 33).return, 34);
     hits++;
 };
-g.eval("f(Proxy.createFunction({}, function (arg) { return arg + 1; }));");
+g.eval("f(new Proxy(function (arg) { return arg + 1; }, {}));");
 assertEq(hits, 1);
--- a/js/src/jit-test/tests/debug/Object-callable.js
+++ b/js/src/jit-test/tests/debug/Object-callable.js
@@ -8,11 +8,11 @@ dbg.onDebuggerStatement = function (fram
     hits++;
 };
 
 g.eval("function f(obj, iscallable) { debugger; }");
 
 g.eval("f({}, false);");
 g.eval("f(Function.prototype, true);");
 g.eval("f(f, true);");
-g.eval("f(Proxy.create({}), false);");
-g.eval("f(Proxy.createFunction(f, f), true);");
+g.eval("f(new Proxy({}, {}), false);");
+g.eval("f(new Proxy(f, {}), true);");
 assertEq(hits, 5);
--- a/js/src/jit-test/tests/debug/Object-class.js
+++ b/js/src/jit-test/tests/debug/Object-class.js
@@ -11,16 +11,16 @@ dbg.onDebuggerStatement = function (fram
     assertEq(arr[2].class, "Function");
     assertEq(arr[3].class, "Date");
     assertEq(arr[4].class, "Object");
     assertEq(arr[5].class, "Function");
     assertEq(arr[6].class, "Date");
     hits++;
 };
 g.f(Object.prototype, [], eval, new Date,
-    Proxy.create({}), Proxy.createFunction({}, eval), new Proxy(new Date, {}));
+    new Proxy({}, {}), new Proxy(eval, {}), new Proxy(new Date, {}));
 assertEq(hits, 1);
 
 // Debugger.Object.prototype.class should see through cross-compartment
 // wrappers.
 g.eval('f(Object.prototype, [], eval, new Date,\
-          Proxy.create({}), Proxy.createFunction({}, f), new Proxy(new Date, {}));');
+          new Proxy({}, {}), new Proxy(f, {}), new Proxy(new Date, {}));');
 assertEq(hits, 2);
--- a/js/src/jit-test/tests/debug/Object-deleteProperty-error-01.js
+++ b/js/src/jit-test/tests/debug/Object-deleteProperty-error-01.js
@@ -7,10 +7,10 @@ dbg.onDebuggerStatement = function (fram
         frame.arguments[0].deleteProperty("x");
     } catch (exc) {
         return;
     }
     throw new Error("deleteProperty should throw");
 };
 
 g.eval("function h(obj) { debugger; }");
-g.eval("h(Proxy.create({delete: function () { throw Error.prototype; }}));");
+g.eval("h(new Proxy({}, { deleteProperty() { throw Error.prototype; }}));");
 
--- a/js/src/jit-test/tests/debug/Object-name-02.js
+++ b/js/src/jit-test/tests/debug/Object-name-02.js
@@ -7,10 +7,10 @@ dbg.onDebuggerStatement = function (fram
     assertEq(frame.arguments[0].name, undefined);
     hits++;
 };
 g.eval("function f(nonfunction) { debugger; }");
 
 g.eval("f({});");
 g.eval("f(/a*/);");
 g.eval("f({name: 'bad'});");
-g.eval("f(Proxy.createFunction({name: {value: 'bad'}}, function () {}));");
+g.eval("f(new Proxy({}, {}));");
 assertEq(hits, 4);
--- a/js/src/jit-test/tests/for-of/array-iterator-proxy.js
+++ b/js/src/jit-test/tests/for-of/array-iterator-proxy.js
@@ -1,47 +1,47 @@
 // An array iterator for a proxy calls the traps in a predictable order.
 
 load(libdir + "asserts.js");
 load(libdir + "iteration.js");
 
 var s = '';
 
-var proxyObj = {
+var handler = {
     get: function (recipient, name) {
         if (name == 'length') {
             s += 'L';
             return 2;
         } else {
             s += name;
             return name;
         }
     }
 };
 
-var it = Array.prototype[Symbol.iterator].call(Proxy.create(proxyObj));
+var it = Array.prototype[Symbol.iterator].call(new Proxy([0, 1], handler));
 
 assertIteratorNext(it, "0");
 s += ' ';
 assertIteratorNext(it, "1");
 s += ' ';
 assertIteratorDone(it, undefined);
 assertEq(s, "L0 L1 L");
 
 s = '';
-var ki = Array.prototype.keys.call(Proxy.create(proxyObj));
+var ki = Array.prototype.keys.call(new Proxy([0, 1], handler));
 
 assertIteratorNext(ki, 0);
 s += ' ';
 assertIteratorNext(ki, 1);
 s += ' ';
 assertIteratorDone(ki, undefined);
 assertEq(s, "L L L");
 
 s = '';
-var ei = Array.prototype.entries.call(Proxy.create(proxyObj));
+var ei = Array.prototype.entries.call(new Proxy([0, 1], handler));
 
 assertIteratorNext(ei, [0, "0"]);
 s += ' ';
 assertIteratorNext(ei, [1, "1"]);
 s += ' ';
 assertIteratorDone(ei, undefined);
 assertEq(s, "L0 L1 L");
--- a/js/src/jit-test/tests/for-of/proxy-1.js
+++ b/js/src/jit-test/tests/for-of/proxy-1.js
@@ -1,28 +1,13 @@
 // Basic for-of test with Proxy.
 
-function iterableProxy(arr) {
-    return Proxy.create({
-        getPropertyDescriptor: function (name) {
-            for (var obj = arr; obj; obj = Object.getPrototypeOf(obj)) {
-                var desc = Object.getOwnPropertyDescriptor(obj, name);
-                if (desc)
-                    return desc;
-            }
-            return undefined;
-        }
-    });
-}
-
 var s = '';
 var arr = ['a', 'b', 'c', 'd'];
-var p = iterableProxy(arr);
+var p = new Proxy(arr, {});
 
-// Test the same proxy twice. Each time through the loop, the proxy handler's
-// getPropertyDescriptor method will be called 10 times (once for 'iterator',
-// five times for 'length', and once for each of the four elements).
+// Test the same proxy twice.
 for (var i = 0; i < 2; i++) {
     var j = 0;
     for (var x of p)
         assertEq(x, arr[j++]);
     assertEq(j, arr.length);
 }
--- a/js/src/jit-test/tests/for-of/proxy-2.js
+++ b/js/src/jit-test/tests/for-of/proxy-2.js
@@ -1,29 +1,18 @@
 // Basic for-of test with Proxy whose iterator method is a generator.
 
 var arr = ['a', 'b', 'c', 'd'];
-var proxy = Proxy.create({
-    getPropertyDescriptor: function (name) {
-        if (name == 'iterator') {
-            return {
-                configurable: false,
-                enumerable: false,
-                writeable: false,
-                value:  function () {
-                    for (var i = 0; i < arr.length; i++)
-                        yield arr[i];
-                }
-            };
+var proxy = new Proxy(arr, {
+    get(target, property, receiver) {
+        if (property === Symbol.iterator) {
+            return function* () {
+                for (var i = 0; i < arr.length; i++)
+                    yield arr[i];
+            }
         }
 
-        // Otherwise, inherit the property from arr.
-        for (var obj = arr; obj; obj = Object.getPrototypeOf(obj)) {
-            var desc = Object.getOwnPropertyDescriptor(obj, name);
-            if (desc)
-                return desc;
-        }
-        return undefined;
+        return Reflect.get(target, property, receiver);
     }
 });
 
 for (var i = 0; i < 2; i++)
     assertEq([...proxy].join(","), "a,b,c,d");
--- a/js/src/jit-test/tests/for-of/proxy-3.js
+++ b/js/src/jit-test/tests/for-of/proxy-3.js
@@ -1,13 +1,13 @@
 // An exception thrown from a proxy trap while getting the .iterator method is propagated.
 
 load(libdir + "asserts.js");
 load(libdir + "iteration.js");
 
-var p = Proxy.create({
-    getPropertyDescriptor: function (name) {
-        if (name == Symbol.iterator)
+var p = new Proxy({}, {
+    get(target, property) {
+        if (property === Symbol.iterator)
             throw "fit";
         return undefined;
     }
 });
 assertThrowsValue(function () { for (var v of p) {} }, "fit");
--- a/js/src/jit-test/tests/for-of/semantics-11.js
+++ b/js/src/jit-test/tests/for-of/semantics-11.js
@@ -1,40 +1,40 @@
 // for-of on a proxy causes a predictable sequence of trap calls.
 
 load(libdir + "iteration.js");
 
 var s = '';
 
 var i = 0;
-var next_fn = Proxy.createFunction({}, function () {
-    s += "n";
-    if (i == 3)
-        return { value: undefined, done: true };
-    return { value: i++, done: false };
+var next_fn = new Proxy(function() {}, {
+    apply() {
+        s += "n";
+        if (i == 3)
+            return { value: undefined, done: true };
+        return { value: i++, done: false };
+    }
 });
 
-var it = Proxy.create({
-    get: function (receiver, name) {
-        if (name == 'toSource') {
-            s += '?';
-            return () => 'it';
-        }
-        assertEq(name, "next");
+var it = new Proxy({}, {
+    get(target, property, receiver) {
+        assertEq(property, "next");
         s += "N";
         return next_fn;
     }
 });
 
-var iterator_fn = Proxy.createFunction({}, function () {
-    s += 'i';
-    return it;
+var iterator_fn = new Proxy(function() {}, {
+    apply() {
+        s += 'i';
+        return it;
+    }
 });
 
-var obj = Proxy.create({
+var obj = new Proxy({}, {
     get: function (receiver, name) {
         assertEq(name, Symbol.iterator);
         s += "I";
         return iterator_fn;
     }
 });
 
 for (var v of obj)
--- a/js/src/jit-test/tests/ion/bug1148973-1.js
+++ b/js/src/jit-test/tests/ion/bug1148973-1.js
@@ -1,17 +1,15 @@
 Object.defineProperty(this, "x", { get: decodeURI, configurable: true })
 try {
-    String(b = Proxy.createFunction(function() {
-        return {
-            get: function(r, z) {
-                return x[z]
-            }
+    String(b = new Proxy(function() { }, {
+        get: function(r, z) {
+            return x[z]
         }
-    }(), function() {}))
+    }))
 } catch (e) {};
 var log = "";
 evaluate(`
 try {
     function x() {}
     assertEq(String(b), "function () {}");
 } catch (e) { log += "e"; }
 `);
--- a/js/src/jit-test/tests/ion/bug724788.js
+++ b/js/src/jit-test/tests/ion/bug724788.js
@@ -1,11 +1,11 @@
 // |jit-test| error: ReferenceError
 o0 = TypeError.prototype.__proto__
-o1 = Proxy.create({})
+o1 = new Proxy({}, {})
 o13 = {}.__proto__
 var o15 = Object.prototype
 o31 = (new Uint32Array(100)).buffer
 function f2(o) {
   try {
     ({
       x: [eval("o")][0]
     }.x.__defineGetter__("toString", function() {
--- a/js/src/jit-test/tests/ion/bug792220.js
+++ b/js/src/jit-test/tests/ion/bug792220.js
@@ -1,9 +1,9 @@
-var p = Proxy.create({
+var p = new Proxy({}, {
   has : function(id) {}
 });
 RegExp.prototype.__proto__ = p;
 function f() {
   if (/a/.exec("a"))
     return 1;
   return 0;
 }
--- a/js/src/jit-test/tests/ion/bug945512.js
+++ b/js/src/jit-test/tests/ion/bug945512.js
@@ -2,11 +2,11 @@
 var handler = {
     has: function (name) {
         assertEq(1, 2);
     }
 };
 
 for (var i=0; i<10; i++) {
     var regex = /undefined/;
-    regex.__proto__ = Proxy.createFunction(handler, function(){})
+    regex.__proto__ = new Proxy(function() {}, handler)
 }
 
--- a/js/src/jit-test/tests/jaeger/bug588338.js
+++ b/js/src/jit-test/tests/jaeger/bug588338.js
@@ -1,16 +1,16 @@
 // |jit-test| error: is not a function
 function f() {
     (e)
 }
-(x = Proxy.createFunction((function(x) {
+(x = new Proxy(Function, (function(x) {
   return {
     get: function(r, b) {
       return x[b]
     }
   }
-})(/x/), Function))
+})(/x/)))
 for (z = 0; z < 100; x.unwatch(), z++)
 for (e in [0]) {
   gczeal(2)
 } ( [1,2,3])("")
 
deleted file mode 100644
--- a/js/src/jit-test/tests/jaeger/bug673788.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// |jit-test| error: ReferenceError
-load(libdir + "immutable-prototype.js");
-
-p = Proxy.create({
-  has: function() {},
-  set: function() {}
-});
-
-if (globalPrototypeChainIsMutable())
-  Object.prototype.__proto__ = p;
-
-n = [];
-(function() {
-  var a = [];
-  if (b) t = a.s()
-})()
--- a/js/src/jit-test/tests/jaeger/bug704138.js
+++ b/js/src/jit-test/tests/jaeger/bug704138.js
@@ -5,20 +5,17 @@ function TestCase(n, d, e, a) {
   return n;
 }
 
 function reportCompare (expected, actual, description) {
   new TestCase
 }
 
 reportCompare(true, "isGenerator" in Function, "Function.prototype.isGenerator present");
-var p = Proxy.create({
-    has : function(id) {},
-    set : function(obj, id, v, rec) {}
-});
+var p = new Proxy({}, {});
 function test() {
     TestCase.prototype.__proto__=null
     if (new TestCase)
         TestCase.prototype.__proto__=p
 }
 test();
 new TestCase;
 test()
--- a/js/src/jit-test/tests/jaeger/recompile/bug641225.js
+++ b/js/src/jit-test/tests/jaeger/recompile/bug641225.js
@@ -1,18 +1,17 @@
 gczeal(1);
 var o0 = Function.prototype;
 o1 = {};
 var o4 = Error.prototype;
 o5 = new Int32Array(100);
-o6 = Proxy.create({
+o6 = new Proxy({}, {})
+o8 = new Proxy(function() { return {}; }, {
+    get: function() { return 10; },
 });
-o8 = Proxy.createFunction({
-    get: function() {return 10; },
-}, function(){ return {}; }, function(){ return {}; });
 o9 = {};
 var o10 = -500;
 var o12 = new Int32Array(100);
 function f0(o) {
 }
 function f1(o) {
 }
 function f3(o) {
deleted file mode 100644
--- a/js/src/jit-test/tests/jaeger/recompile/bug643552.js
+++ /dev/null
@@ -1,2 +0,0 @@
-var x = Proxy.create( {get:function(r,name){Proxy = 0;}} );
-try { x.watch('e', function(){}); } catch (e) {}
deleted file mode 100644
--- a/js/src/jit-test/tests/proxy/testIndirectProxyGetOwnPropertyDescriptor.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// Bug 1133294 - Object.getOwnPropertyDescriptor should never return an incomplete descriptor.
-
-load(libdir + "asserts.js");
-
-var p = Proxy.create({ getOwnPropertyDescriptor() { return {}; } });
-var desc = Object.getOwnPropertyDescriptor(p, "x");
-assertDeepEq(desc, {
-    value: undefined,
-    writable: false,
-    enumerable: false,
-    configurable: false
-});
deleted file mode 100644
--- a/js/src/jit-test/tests/proxy/testIndirectProxySet.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// BaseProxyHandler::set correctly defines a property on receiver if the
-// property being assigned doesn't exist anywhere on the proto chain.
-
-var p = Proxy.create({
-    getOwnPropertyDescriptor() { return undefined; },
-    getPropertyDescriptor() { return undefined; },
-    defineProperty() { throw "FAIL"; }
-});
-var q = new Proxy(p, {
-    defineProperty(t, id, desc) {
-        assertEq(t, p);
-        assertEq(id, "x");
-        assertEq(desc.configurable, true);
-        assertEq(desc.enumerable, true);
-        assertEq(desc.writable, true);
-        assertEq(desc.value, 3);
-        hits++;
-        return true;
-    }
-});
-var hits = 0;
-
-// This assignment eventually reaches ScriptedIndirectProxyHandler::set
-// with arguments (proxy=p, receiver=q). Test that it finishes by defining
-// a property on receiver, not on proxy.
-q.x = 3;
-assertEq(hits, 1);
--- a/js/src/jit/FixedList.h
+++ b/js/src/jit/FixedList.h
@@ -27,17 +27,17 @@ class FixedList
     void operator= (const FixedList*); // no assignment definition.
 
   public:
     FixedList()
       : list_(nullptr), length_(0)
     { }
 
     // Dynamic memory allocation requires the ability to report failure.
-    bool init(TempAllocator& alloc, size_t length) {
+    MOZ_WARN_UNUSED_RESULT bool init(TempAllocator& alloc, size_t length) {
         length_ = length;
         if (length == 0)
             return true;
 
         size_t bytes;
         if (MOZ_UNLIKELY(!CalculateAllocSize<T>(length, &bytes)))
             return false;
         list_ = (T*)alloc.allocate(bytes);
@@ -52,17 +52,17 @@ class FixedList
         return length_;
     }
 
     void shrink(size_t num) {
         MOZ_ASSERT(num < length_);
         length_ -= num;
     }
 
-    bool growBy(TempAllocator& alloc, size_t num) {
+    MOZ_WARN_UNUSED_RESULT bool growBy(TempAllocator& alloc, size_t num) {
         size_t newlength = length_ + num;
         if (newlength < length_)
             return false;
         size_t bytes;
         if (MOZ_UNLIKELY(!CalculateAllocSize<T>(newlength, &bytes)))
             return false;
         T* list = (T*)alloc.allocate(bytes);
         if (MOZ_UNLIKELY(!list))
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -5873,17 +5873,18 @@ IonBuilder::inlineCalls(CallInfo& callIn
     returnBlock->inheritSlots(dispatchBlock);
     callInfo.popFormals(returnBlock);
 
     MPhi* retPhi = MPhi::New(alloc());
     returnBlock->addPhi(retPhi);
     returnBlock->push(retPhi);
 
     // Create a resume point from current stack state.
-    returnBlock->initEntrySlots(alloc());
+    if (!returnBlock->initEntrySlots(alloc()))
+        return false;
 
     // Reserve the capacity for the phi.
     // Note: this is an upperbound. Unreachable targets and uninlineable natives are also counted.
     uint32_t count = 1; // Possible fallback block.
     for (uint32_t i = 0; i < targets.length(); i++) {
         if (choiceSet[i])
             count++;
     }
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -1216,17 +1216,17 @@ class MQuaternaryInstruction : public MA
 };
 
 template <class T>
 class MVariadicT : public T
 {
     FixedList<MUse> operands_;
 
   protected:
-    bool init(TempAllocator& alloc, size_t length) {
+    MOZ_WARN_UNUSED_RESULT bool init(TempAllocator& alloc, size_t length) {
         return operands_.init(alloc, length);
     }
     void initOperand(size_t index, MDefinition* operand) {
         // FixedList doesn't initialize its elements, so do an unchecked init.
         operands_[index].initUnchecked(operand, this);
     }
     MUse* getUseFor(size_t index) final override {
         return &operands_[index];
@@ -2017,17 +2017,17 @@ class MSimdGeneralShuffle :
     INSTRUCTION_HEADER(SimdGeneralShuffle);
 
     static MSimdGeneralShuffle* New(TempAllocator& alloc, unsigned numVectors, unsigned numLanes,
                                     MIRType type)
     {
         return new(alloc) MSimdGeneralShuffle(numVectors, numLanes, type);
     }
 
-    bool init(TempAllocator& alloc) {
+    MOZ_WARN_UNUSED_RESULT bool init(TempAllocator& alloc) {
         return MVariadicInstruction::init(alloc, numVectors_ + numLanes_);
     }
     void setVector(unsigned i, MDefinition* vec) {
         MOZ_ASSERT(i < numVectors_);
         initOperand(i, vec);
     }
     void setLane(unsigned i, MDefinition* laneIndex) {
         MOZ_ASSERT(i < numLanes_);
@@ -2661,17 +2661,17 @@ class MTableSwitch final
   public:
     INSTRUCTION_HEADER(TableSwitch)
     static MTableSwitch* New(TempAllocator& alloc, MDefinition* ins, int32_t low, int32_t high);
 
     size_t numSuccessors() const override {
         return successors_.length();
     }
 
-    bool addSuccessor(MBasicBlock* successor, size_t* index) {
+    MOZ_WARN_UNUSED_RESULT bool addSuccessor(MBasicBlock* successor, size_t* index) {
         MOZ_ASSERT(successors_.length() < (size_t)(high_ - low_ + 2));
         MOZ_ASSERT(!successors_.empty());
         *index = successors_.length();
         return successors_.append(successor);
     }
 
     MBasicBlock* getSuccessor(size_t i) const override {
         MOZ_ASSERT(i < numSuccessors());
@@ -2706,33 +2706,33 @@ class MTableSwitch final
     MBasicBlock* getCase(size_t i) const {
         return getSuccessor(cases_[i]);
     }
 
     size_t numCases() const {
         return high() - low() + 1;
     }
 
-    bool addDefault(MBasicBlock* block, size_t* index = nullptr) {
+    MOZ_WARN_UNUSED_RESULT bool addDefault(MBasicBlock* block, size_t* index = nullptr) {
         MOZ_ASSERT(successors_.empty());
         if (index)
             *index = 0;
         return successors_.append(block);
     }
 
-    bool addCase(size_t successorIndex) {
+    MOZ_WARN_UNUSED_RESULT bool addCase(size_t successorIndex) {
         return cases_.append(successorIndex);
     }
 
     MBasicBlock* getBlock(size_t i) const {
         MOZ_ASSERT(i < numBlocks());
         return blocks_[i];
     }
 
-    bool addBlock(MBasicBlock* block) {
+    MOZ_WARN_UNUSED_RESULT bool addBlock(MBasicBlock* block) {
         return blocks_.append(block);
     }
 
     MDefinition* getOperand(size_t index) const override {
         MOZ_ASSERT(index == 0);
         return operand_.producer();
     }
 
@@ -3623,17 +3623,17 @@ class MArrayState
   : public MVariadicInstruction,
     public NoFloatPolicyAfter<2>::Data
 {
   private:
     uint32_t numElements_;
 
     explicit MArrayState(MDefinition* arr);
 
-    bool init(TempAllocator& alloc, MDefinition* obj, MDefinition* len);
+    MOZ_WARN_UNUSED_RESULT bool init(TempAllocator& alloc, MDefinition* obj, MDefinition* len);
 
     void initElement(uint32_t index, MDefinition* def) {
         initOperand(index + 2, def);
     }
 
   public:
     INSTRUCTION_HEADER(ArrayState)
 
@@ -13243,17 +13243,17 @@ class MResumePoint final :
     Mode mode_;
 
     MResumePoint(MBasicBlock* block, jsbytecode* pc, Mode mode);
     void inherit(MBasicBlock* state);
 
   protected:
     // Initializes operands_ to an empty array of a fixed length.
     // The array may then be filled in by inherit().
-    bool init(TempAllocator& alloc);
+    MOZ_WARN_UNUSED_RESULT bool init(TempAllocator& alloc);
 
     void clearOperand(size_t index) {
         // FixedList doesn't initialize its elements, so do an unchecked init.
         operands_[index].initUncheckedWithoutProducer(this);
     }
 
     MUse* getUseFor(size_t index) override {
         return &operands_[index];
--- a/js/src/jit/MIRGraph.h
+++ b/js/src/jit/MIRGraph.h
@@ -42,21 +42,21 @@ class MBasicBlock : public TempObject, p
         PENDING_LOOP_HEADER,
         LOOP_HEADER,
         SPLIT_EDGE,
         DEAD
     };
 
   private:
     MBasicBlock(MIRGraph& graph, const CompileInfo& info, BytecodeSite* site, Kind kind);
-    bool init();
+    MOZ_WARN_UNUSED_RESULT bool init();
     void copySlots(MBasicBlock* from);
-    bool inherit(TempAllocator& alloc, BytecodeAnalysis* analysis, MBasicBlock* pred,
-                 uint32_t popped, unsigned stackPhiCount = 0);
-    bool inheritResumePoint(MBasicBlock* pred);
+    MOZ_WARN_UNUSED_RESULT bool inherit(TempAllocator& alloc, BytecodeAnalysis* analysis, MBasicBlock* pred,
+                                        uint32_t popped, unsigned stackPhiCount = 0);
+    MOZ_WARN_UNUSED_RESULT bool inheritResumePoint(MBasicBlock* pred);
     void assertUsesAreNotWithin(MUseIterator use, MUseIterator end);
 
     // This block cannot be reached by any means.
     bool unreachable_;
 
     // Pushes a copy of a local variable or argument.
     void pushVariable(uint32_t slot);
 
@@ -147,29 +147,29 @@ class MBasicBlock : public TempObject, p
 
     // Gets the instruction associated with various slot types.
     MDefinition* peek(int32_t depth);
 
     MDefinition* scopeChain();
     MDefinition* argumentsObject();
 
     // Increase the number of slots available
-    bool increaseSlots(size_t num);
-    bool ensureHasSlots(size_t num);
+    MOZ_WARN_UNUSED_RESULT bool increaseSlots(size_t num);
+    MOZ_WARN_UNUSED_RESULT bool ensureHasSlots(size_t num);
 
     // Initializes a slot value; must not be called for normal stack
     // operations, as it will not create new SSA names for copies.
     void initSlot(uint32_t index, MDefinition* ins);
 
     // Discard the slot at the given depth, lowering all slots above.
     void shimmySlots(int discardDepth);
 
     // In an OSR block, set all MOsrValues to use the MResumePoint attached to
     // the MStart.
-    bool linkOsrValues(MStart* start);
+    MOZ_WARN_UNUSED_RESULT bool linkOsrValues(MStart* start);
 
     // Sets the instruction associated with various slot types. The
     // instruction must lie at the top of the stack.
     void setLocal(uint32_t local);
     void setArg(uint32_t arg);
     void setSlot(uint32_t slot);
     void setSlot(uint32_t slot, MDefinition* ins);
 
@@ -213,27 +213,27 @@ class MBasicBlock : public TempObject, p
     void discardPreAllocatedResumePoint(MResumePoint* resume) {
         MOZ_ASSERT(!resume->instruction());
         discardResumePoint(resume);
     }
 
     // Adds a predecessor. Every predecessor must have the same exit stack
     // depth as the entry state to this block. Adding a predecessor
     // automatically creates phi nodes and rewrites uses as needed.
-    bool addPredecessor(TempAllocator& alloc, MBasicBlock* pred);
-    bool addPredecessorPopN(TempAllocator& alloc, MBasicBlock* pred, uint32_t popped);
+    MOZ_WARN_UNUSED_RESULT bool addPredecessor(TempAllocator& alloc, MBasicBlock* pred);
+    MOZ_WARN_UNUSED_RESULT bool addPredecessorPopN(TempAllocator& alloc, MBasicBlock* pred, uint32_t popped);
 
     // Add a predecessor which won't introduce any new phis to this block.
     // This may be called after the contents of this block have been built.
     void addPredecessorSameInputsAs(MBasicBlock* pred, MBasicBlock* existingPred);
 
     // Stranger utilities used for inlining.
-    bool addPredecessorWithoutPhis(MBasicBlock* pred);
+    MOZ_WARN_UNUSED_RESULT bool addPredecessorWithoutPhis(MBasicBlock* pred);
     void inheritSlots(MBasicBlock* parent);
-    bool initEntrySlots(TempAllocator& alloc);
+    MOZ_WARN_UNUSED_RESULT bool initEntrySlots(TempAllocator& alloc);
 
     // Replaces an edge for a given block with a new block. This is
     // used for critical edge splitting.
     //
     // Note: If successorWithPhis is set, you must not be replacing it.
     void replacePredecessor(MBasicBlock* old, MBasicBlock* split);
     void replaceSuccessor(size_t pos, MBasicBlock* split);
 
@@ -248,36 +248,36 @@ class MBasicBlock : public TempObject, p
     void removePredecessorWithoutPhiOperands(MBasicBlock* pred, size_t predIndex);
 
     // Resets all the dominator info so that it can be recomputed.
     void clearDominatorInfo();
 
     // Sets a back edge. This places phi nodes and rewrites instructions within
     // the current loop as necessary. If the backedge introduces new types for
     // phis at the loop header, returns a disabling abort.
-    AbortReason setBackedge(MBasicBlock* block);
-    bool setBackedgeAsmJS(MBasicBlock* block);
+    MOZ_WARN_UNUSED_RESULT AbortReason setBackedge(MBasicBlock* block);
+    MOZ_WARN_UNUSED_RESULT bool setBackedgeAsmJS(MBasicBlock* block);
 
     // Resets a LOOP_HEADER block to a NORMAL block.  This is needed when
     // optimizations remove the backedge.
     void clearLoopHeader();
 
     // Sets a block to a LOOP_HEADER block, with newBackedge as its backedge.
     // This is needed when optimizations remove the normal entry to a loop
     // with multiple entries.
     void setLoopHeader(MBasicBlock* newBackedge);
 
     // Propagates phis placed in a loop header down to this successor block.
     void inheritPhis(MBasicBlock* header);
 
     // Propagates backedge slots into phis operands of the loop header.
-    bool inheritPhisFromBackedge(MBasicBlock* backedge, bool* hadTypeChange);
+    MOZ_WARN_UNUSED_RESULT bool inheritPhisFromBackedge(MBasicBlock* backedge, bool* hadTypeChange);
 
     // Compute the types for phis in this block according to their inputs.
-    bool specializePhis();
+    MOZ_WARN_UNUSED_RESULT bool specializePhis();
 
     void insertBefore(MInstruction* at, MInstruction* ins);
     void insertAfter(MInstruction* at, MInstruction* ins);
 
     void insertAtEnd(MInstruction* ins);
 
     // Add an instruction to this block, from elsewhere in the graph.
     void addFromElsewhere(MInstruction* ins);
@@ -759,17 +759,17 @@ class MIRGraph
 
     void setReturnAccumulator(MIRGraphReturns* accum) {
         returnAccumulator_ = accum;
     }
     MIRGraphReturns* returnAccumulator() const {
         return returnAccumulator_;
     }
 
-    bool addReturn(MBasicBlock* returnBlock) {
+    MOZ_WARN_UNUSED_RESULT bool addReturn(MBasicBlock* returnBlock) {
         if (!returnAccumulator_)
             return true;
 
         return returnAccumulator_->append(returnBlock);
     }
 
     MBasicBlock* entryBlock() {
         return *blocks_.begin();
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -375,17 +375,16 @@ MSG_DEF(JSMSG_MUST_REPORT_SAME_VALUE,  0
 MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED,   0, JSEXN_TYPEERR, "proxy must report undefined for a non-configurable accessor property without a getter")
 MSG_DEF(JSMSG_OBJECT_ACCESS_DENIED,    0, JSEXN_ERR, "Permission denied to access object")
 MSG_DEF(JSMSG_PROPERTY_ACCESS_DENIED,  1, JSEXN_ERR, "Permission denied to access property {0}")
 MSG_DEF(JSMSG_PROXY_CONSTRUCT_OBJECT,  0, JSEXN_TYPEERR, "proxy [[Construct]] must return an object")
 MSG_DEF(JSMSG_PROXY_EXTENSIBILITY,     0, JSEXN_TYPEERR, "proxy must report same extensiblitity as target")
 MSG_DEF(JSMSG_PROXY_GETOWN_OBJORUNDEF, 0, JSEXN_TYPEERR, "proxy [[GetOwnProperty]] must return an object or undefined")
 MSG_DEF(JSMSG_PROXY_REVOKED,           0, JSEXN_TYPEERR, "illegal operation attempted on a revoked proxy")
 MSG_DEF(JSMSG_PROXY_ARG_REVOKED,       1, JSEXN_TYPEERR, "argument {0} cannot be a revoked proxy")
-MSG_DEF(JSMSG_DEPRECATED_PROXY_CREATE, 0, JSEXN_NONE, "Proxy.create and Proxy.createFunction are deprecated, use new Proxy instead")
 
 // Structured cloning
 MSG_DEF(JSMSG_SC_BAD_CLONE_VERSION,    0, JSEXN_ERR, "unsupported structured clone version")
 MSG_DEF(JSMSG_SC_BAD_SERIALIZED_DATA,  1, JSEXN_INTERNALERR, "bad serialized structured data ({0})")
 MSG_DEF(JSMSG_SC_DUP_TRANSFERABLE,     0, JSEXN_TYPEERR, "duplicate transferable for structured clone")
 MSG_DEF(JSMSG_SC_NOT_TRANSFERABLE,     0, JSEXN_TYPEERR, "invalid transferable array for structured clone")
 MSG_DEF(JSMSG_SC_UNSUPPORTED_TYPE,     0, JSEXN_TYPEERR, "unsupported type for structured data")
 MSG_DEF(JSMSG_SC_SHMEM_MUST_TRANSFER,  0, JSEXN_TYPEERR, "SharedArrayBuffer must be explicitly transfered during structured cloning")
--- a/js/src/jsapi-tests/testJitDCEinGVN.cpp
+++ b/js/src/jsapi-tests/testJitDCEinGVN.cpp
@@ -86,44 +86,44 @@ BEGIN_TEST(testJitDCEinGVN_phi)
 
     //   x = 1.0
     //   y = 3.0;
     x->addInputSlow(c1);
     MConstant* c3 = MConstant::New(func.alloc, DoubleValue(3.0));
     thenBlock1->add(c3);
     y->addInputSlow(c3);
     thenBlock1->end(MGoto::New(func.alloc, joinBlock));
-    joinBlock->addPredecessor(func.alloc, thenBlock1);
+    MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, thenBlock1));
 
     // } else if (q) {
     MParameter* q = func.createParameter();
     elifBlock->add(q);
     elifBlock->end(MTest::New(func.alloc, q, thenBlock2, elseBlock));
 
     //   x = 2.0
     //   y = 4.0;
     MConstant* c2 = MConstant::New(func.alloc, DoubleValue(2.0));
     thenBlock2->add(c2);
     x->addInputSlow(c2);
     MConstant* c4 = MConstant::New(func.alloc, DoubleValue(4.0));
     thenBlock2->add(c4);
     y->addInputSlow(c4);
     thenBlock2->end(MGoto::New(func.alloc, joinBlock));
-    joinBlock->addPredecessor(func.alloc, thenBlock2);
+    MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, thenBlock2));
 
     // } else {
     //   x = 1.0
     //   y = 5.0;
     // }
     x->addInputSlow(c1);
     MConstant* c5 = MConstant::New(func.alloc, DoubleValue(5.0));
     elseBlock->add(c5);
     y->addInputSlow(c5);
     elseBlock->end(MGoto::New(func.alloc, joinBlock));
-    joinBlock->addPredecessor(func.alloc, elseBlock);
+    MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, elseBlock));
 
     // x = phi(1.0, 2.0, 1.0)
     // y = phi(3.0, 4.0, 5.0)
     // z = x * y
     // return y
     joinBlock->addPhi(x);
     joinBlock->addPhi(y);
     MMul* z = MMul::New(func.alloc, x, y, MIRType_Double);
--- a/js/src/jsapi-tests/testJitFoldsTo.cpp
+++ b/js/src/jsapi-tests/testJitFoldsTo.cpp
@@ -151,17 +151,17 @@ BEGIN_TEST(testJitNotTest)
 
     then->end(MGoto::New(func.alloc, exit));
 
     else_->end(MGoto::New(func.alloc, exit));
 
     MReturn* ret = MReturn::New(func.alloc, p);
     exit->end(ret);
 
-    exit->addPredecessorWithoutPhis(then);
+    MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(then));
 
     if (!func.runGVN())
         return false;
 
     // Test that the not got folded.
     test = block->lastIns()->toTest();
     CHECK(test->getOperand(0) == p);
     CHECK(test->getSuccessor(0) == else_);
@@ -190,17 +190,17 @@ BEGIN_TEST(testJitNotNotTest)
 
     then->end(MGoto::New(func.alloc, exit));
 
     else_->end(MGoto::New(func.alloc, exit));
 
     MReturn* ret = MReturn::New(func.alloc, p);
     exit->end(ret);
 
-    exit->addPredecessorWithoutPhis(then);
+    MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(then));
 
     if (!func.runGVN())
         return false;
 
     // Test that the nots got folded.
     test = block->lastIns()->toTest();
     CHECK(test->getOperand(0) == p);
     CHECK(test->getSuccessor(0) == then);
--- a/js/src/jsapi-tests/testJitGVN.cpp
+++ b/js/src/jsapi-tests/testJitGVN.cpp
@@ -63,20 +63,20 @@ BEGIN_TEST(testJitGVN_FixupOSROnlyLoop)
 
     innerBackedge->end(MGoto::New(func.alloc, innerHeader));
     outerBackedge->end(MGoto::New(func.alloc, outerHeader));
 
     MConstant* u = MConstant::New(func.alloc, UndefinedValue());
     exit->add(u);
     exit->end(MReturn::New(func.alloc, u));
 
-    innerHeader->addPredecessorWithoutPhis(innerBackedge);
-    outerHeader->addPredecessorWithoutPhis(outerBackedge);
-    exit->addPredecessorWithoutPhis(entry);
-    merge->addPredecessorWithoutPhis(osrEntry);
+    MOZ_ALWAYS_TRUE(innerHeader->addPredecessorWithoutPhis(innerBackedge));
+    MOZ_ALWAYS_TRUE(outerHeader->addPredecessorWithoutPhis(outerBackedge));
+    MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(entry));
+    MOZ_ALWAYS_TRUE(merge->addPredecessorWithoutPhis(osrEntry));
 
     outerHeader->setLoopHeader(outerBackedge);
     innerHeader->setLoopHeader(innerBackedge);
 
     if (!func.runGVN())
         return false;
 
     // The loops are no longer reachable from the normal entry. They are
@@ -155,21 +155,21 @@ BEGIN_TEST(testJitGVN_FixupOSROnlyLoopNe
     innerBackedge->end(MGoto::New(func.alloc, innerHeader));
     middleBackedge->end(MGoto::New(func.alloc, middleHeader));
     outerBackedge->end(MGoto::New(func.alloc, outerHeader));
 
     MConstant* u = MConstant::New(func.alloc, UndefinedValue());
     exit->add(u);
     exit->end(MReturn::New(func.alloc, u));
 
-    innerHeader->addPredecessorWithoutPhis(innerBackedge);
-    middleHeader->addPredecessorWithoutPhis(middleBackedge);
-    outerHeader->addPredecessorWithoutPhis(outerBackedge);
-    exit->addPredecessorWithoutPhis(entry);
-    merge->addPredecessorWithoutPhis(osrEntry);
+    MOZ_ALWAYS_TRUE(innerHeader->addPredecessorWithoutPhis(innerBackedge));
+    MOZ_ALWAYS_TRUE(middleHeader->addPredecessorWithoutPhis(middleBackedge));
+    MOZ_ALWAYS_TRUE(outerHeader->addPredecessorWithoutPhis(outerBackedge));
+    MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(entry));
+    MOZ_ALWAYS_TRUE(merge->addPredecessorWithoutPhis(osrEntry));
 
     outerHeader->setLoopHeader(outerBackedge);
     middleHeader->setLoopHeader(middleBackedge);
     innerHeader->setLoopHeader(innerBackedge);
 
     if (!func.runGVN())
         return false;
 
@@ -264,18 +264,18 @@ BEGIN_TEST(testJitGVN_PinnedPhis)
     phi2->addInputSlow(z6);
     phi3->addInputSlow(z7);
     exit->add(z4);
     exit->add(z5);
     exit->add(z6);
     exit->add(z7);
     exit->end(MGoto::New(func.alloc, outerHeader));
 
-    innerHeader->addPredecessorWithoutPhis(innerBackedge);
-    outerHeader->addPredecessorWithoutPhis(exit);
+    MOZ_ALWAYS_TRUE(innerHeader->addPredecessorWithoutPhis(innerBackedge));
+    MOZ_ALWAYS_TRUE(outerHeader->addPredecessorWithoutPhis(exit));
 
     outerHeader->setLoopHeader(exit);
     innerHeader->setLoopHeader(innerBackedge);
 
     if (!func.runGVN())
         return false;
 
     MOZ_RELEASE_ASSERT(innerHeader->phisEmpty());
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5780,16 +5780,28 @@ JS_PUBLIC_API(JSErrorReport*)
 JS_ErrorFromException(JSContext* cx, HandleObject obj)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return ErrorFromException(cx, obj);
 }
 
+void
+JSErrorReport::initLinebuf(const char16_t* linebuf, size_t linebufLength, size_t tokenOffset)
+{
+    MOZ_ASSERT(linebuf);
+    MOZ_ASSERT(tokenOffset <= linebufLength);
+    MOZ_ASSERT(linebuf[linebufLength] == '\0');
+
+    linebuf_ = linebuf;
+    linebufLength_ = linebufLength;
+    tokenOffset_ = tokenOffset;
+}
+
 JS_PUBLIC_API(bool)
 JS_ThrowStopIteration(JSContext* cx)
 {
     AssertHeapIsIdle(cx);
     return ThrowStopIteration(cx);
 }
 
 JS_PUBLIC_API(bool)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4938,36 +4938,53 @@ JS_ReportOutOfMemory(JSContext* cx);
 /**
  * Complain when an allocation size overflows the maximum supported limit.
  */
 extern JS_PUBLIC_API(void)
 JS_ReportAllocationOverflow(JSContext* cx);
 
 class JSErrorReport
 {
+    // Offending source line without final '\n'.
+    const char16_t* linebuf_;
+
+    // Number of chars in linebuf_. Does not include trailing '\0'.
+    size_t linebufLength_;
+
+    // The 0-based offset of error token in linebuf_.
+    size_t tokenOffset_;
+
   public:
     JSErrorReport()
-      : filename(nullptr), lineno(0), column(0), isMuted(false), linebuf(nullptr),
-        tokenptr(nullptr), uclinebuf(nullptr), uctokenptr(nullptr), flags(0), errorNumber(0),
-        ucmessage(nullptr), messageArgs(nullptr), exnType(0)
+      : linebuf_(nullptr), linebufLength_(0), tokenOffset_(0),
+        filename(nullptr), lineno(0), column(0), isMuted(false),
+        flags(0), errorNumber(0), ucmessage(nullptr),
+        messageArgs(nullptr), exnType(0)
     {}
 
     const char*     filename;      /* source file name, URL, etc., or null */
     unsigned        lineno;         /* source line number */
     unsigned        column;         /* zero-based column index in line */
     bool            isMuted;        /* See the comment in ReadOnlyCompileOptions. */
-    const char*     linebuf;       /* offending source line without final \n */
-    const char*     tokenptr;      /* pointer to error token in linebuf */
-    const char16_t* uclinebuf;     /* unicode (original) line buffer */
-    const char16_t* uctokenptr;    /* unicode (original) token pointer */
     unsigned        flags;          /* error/warning, etc. */
     unsigned        errorNumber;    /* the error number, e.g. see js.msg */
     const char16_t* ucmessage;     /* the (default) error message */
     const char16_t** messageArgs;  /* arguments for the error message */
     int16_t         exnType;        /* One of the JSExnType constants */
+
+    const char16_t* linebuf() const {
+        return linebuf_;
+    }
+    size_t linebufLength() const {
+        return linebufLength_;
+    }
+    size_t tokenOffset() const {
+        return tokenOffset_;
+    }
+    void initLinebuf(const char16_t* linebuf, size_t linebufLength, size_t tokenOffset);
 };
 
 /*
  * JSErrorReport flag values.  These may be freely composed.
  */
 #define JSREPORT_ERROR      0x0     /* pseudo-flag for default case */
 #define JSREPORT_WARNING    0x1     /* reported via JS_ReportWarning */
 #define JSREPORT_EXCEPTION  0x2     /* exception was thrown */
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -432,17 +432,17 @@ js::AtomizeUTF8Chars(JSContext* cx, cons
 {
     // This could be optimized to hand the char16_t's directly to the JSAtom
     // instead of making a copy. UTF8CharsToNewTwoByteCharsZ should be
     // refactored to take an ExclusiveContext so that this function could also.
 
     UTF8Chars utf8(utf8Chars, utf8ByteLength);
 
     size_t length;
-    UniquePtr<char16_t> chars(JS::UTF8CharsToNewTwoByteCharsZ(cx, utf8, &length).get());
+    UniqueTwoByteChars chars(JS::UTF8CharsToNewTwoByteCharsZ(cx, utf8, &length).get());
     if (!chars)
         return nullptr;
 
     return AtomizeChars(cx, chars.get(), length);
 }
 
 bool
 js::IndexToIdSlow(ExclusiveContext* cx, uint32_t index, MutableHandleId idp)
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -514,30 +514,38 @@ js::PrintError(JSContext* cx, FILE* file
         message = ctmp;
     }
 
     /* If there were no filename or lineno, the prefix might be empty */
     if (prefix)
         fputs(prefix, file);
     fputs(message, file);
 
-    if (report->linebuf) {
-        /* report->linebuf usually ends with a newline. */
-        int n = strlen(report->linebuf);
-        fprintf(file, ":\n%s%s%s%s",
-                prefix,
-                report->linebuf,
-                (n > 0 && report->linebuf[n-1] == '\n') ? "" : "\n",
-                prefix);
-        n = report->tokenptr - report->linebuf;
-        for (int i = 0, j = 0; i < n; i++) {
-            if (report->linebuf[i] == '\t') {
-                for (int k = (j + 8) & ~7; j < k; j++) {
+    if (const char16_t* linebuf = report->linebuf()) {
+        size_t n = report->linebufLength();
+
+        fputs(":\n", file);
+        if (prefix)
+            fputs(prefix, file);
+
+        for (size_t i = 0; i < n; i++)
+            fputc(static_cast<char>(linebuf[i]), file);
+
+        // linebuf usually ends with a newline. If not, add one here.
+        if (n == 0 || linebuf[n-1] != '\n')
+            fputc('\n', file);
+
+        if (prefix)
+            fputs(prefix, file);
+
+        n = report->tokenOffset();
+        for (size_t i = 0, j = 0; i < n; i++) {
+            if (linebuf[i] == '\t') {
+                for (size_t k = (j + 8) & ~7; j < k; j++)
                     fputc('.', file);
-                }
                 continue;
             }
             fputc('.', file);
             j++;
         }
         fputc('^', file);
     }
     fputc('\n', file);
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -143,105 +143,84 @@ js::CopyErrorReport(JSContext* cx, JSErr
 {
     /*
      * We use a single malloc block to make a deep copy of JSErrorReport with
      * the following layout:
      *   JSErrorReport
      *   array of copies of report->messageArgs
      *   char16_t array with characters for all messageArgs
      *   char16_t array with characters for ucmessage
-     *   char16_t array with characters for uclinebuf and uctokenptr
-     *   char array with characters for linebuf and tokenptr
+     *   char16_t array with characters for linebuf
      *   char array with characters for filename
      * Such layout together with the properties enforced by the following
      * asserts does not need any extra alignment padding.
      */
     JS_STATIC_ASSERT(sizeof(JSErrorReport) % sizeof(const char*) == 0);
     JS_STATIC_ASSERT(sizeof(const char*) % sizeof(char16_t) == 0);
 
-    size_t filenameSize;
-    size_t linebufSize;
-    size_t uclinebufSize;
-    size_t ucmessageSize;
-    size_t i, argsArraySize, argsCopySize, argSize;
-    size_t mallocSize;
-    JSErrorReport* copy;
-    uint8_t* cursor;
-
 #define JS_CHARS_SIZE(chars) ((js_strlen(chars) + 1) * sizeof(char16_t))
 
-    filenameSize = report->filename ? strlen(report->filename) + 1 : 0;
-    linebufSize = report->linebuf ? strlen(report->linebuf) + 1 : 0;
-    uclinebufSize = report->uclinebuf ? JS_CHARS_SIZE(report->uclinebuf) : 0;
-    ucmessageSize = 0;
-    argsArraySize = 0;
-    argsCopySize = 0;
+    size_t filenameSize = report->filename ? strlen(report->filename) + 1 : 0;
+    size_t linebufSize = 0;
+    if (report->linebuf())
+        linebufSize = (report->linebufLength() + 1) * sizeof(char16_t);
+    size_t ucmessageSize = 0;
+    size_t argsArraySize = 0;
+    size_t argsCopySize = 0;
     if (report->ucmessage) {
         ucmessageSize = JS_CHARS_SIZE(report->ucmessage);
         if (report->messageArgs) {
-            for (i = 0; report->messageArgs[i]; ++i)
+            size_t i = 0;
+            for (; report->messageArgs[i]; ++i)
                 argsCopySize += JS_CHARS_SIZE(report->messageArgs[i]);
 
             /* Non-null messageArgs should have at least one non-null arg. */
             MOZ_ASSERT(i != 0);
             argsArraySize = (i + 1) * sizeof(const char16_t*);
         }
     }
 
     /*
      * The mallocSize can not overflow since it represents the sum of the
      * sizes of already allocated objects.
      */
-    mallocSize = sizeof(JSErrorReport) + argsArraySize + argsCopySize +
-                 ucmessageSize + uclinebufSize + linebufSize + filenameSize;
-    cursor = cx->pod_malloc<uint8_t>(mallocSize);
+    size_t mallocSize = sizeof(JSErrorReport) + argsArraySize + argsCopySize +
+                         ucmessageSize + linebufSize + filenameSize;
+    uint8_t* cursor = cx->pod_calloc<uint8_t>(mallocSize);
     if (!cursor)
         return nullptr;
 
-    copy = (JSErrorReport*)cursor;
-    memset(cursor, 0, sizeof(JSErrorReport));
+    JSErrorReport* copy = (JSErrorReport*)cursor;
     cursor += sizeof(JSErrorReport);
 
     if (argsArraySize != 0) {
         copy->messageArgs = (const char16_t**)cursor;
         cursor += argsArraySize;
-        for (i = 0; report->messageArgs[i]; ++i) {
+        size_t i = 0;
+        for (; report->messageArgs[i]; ++i) {
             copy->messageArgs[i] = (const char16_t*)cursor;
-            argSize = JS_CHARS_SIZE(report->messageArgs[i]);
+            size_t argSize = JS_CHARS_SIZE(report->messageArgs[i]);
             js_memcpy(cursor, report->messageArgs[i], argSize);
             cursor += argSize;
         }
         copy->messageArgs[i] = nullptr;
         MOZ_ASSERT(cursor == (uint8_t*)copy->messageArgs[0] + argsCopySize);
     }
 
     if (report->ucmessage) {
         copy->ucmessage = (const char16_t*)cursor;
         js_memcpy(cursor, report->ucmessage, ucmessageSize);
         cursor += ucmessageSize;
     }
 
-    if (report->uclinebuf) {
-        copy->uclinebuf = (const char16_t*)cursor;
-        js_memcpy(cursor, report->uclinebuf, uclinebufSize);
-        cursor += uclinebufSize;
-        if (report->uctokenptr) {
-            copy->uctokenptr = copy->uclinebuf + (report->uctokenptr -
-                                                  report->uclinebuf);
-        }
-    }
-
-    if (report->linebuf) {
-        copy->linebuf = (const char*)cursor;
-        js_memcpy(cursor, report->linebuf, linebufSize);
+    if (report->linebuf()) {
+        const char16_t* linebufCopy = (const char16_t*)cursor;
+        js_memcpy(cursor, report->linebuf(), linebufSize);
         cursor += linebufSize;
-        if (report->tokenptr) {
-            copy->tokenptr = copy->linebuf + (report->tokenptr -
-                                              report->linebuf);
-        }
+        copy->initLinebuf(linebufCopy, report->linebufLength(), report->tokenOffset());
     }
 
     if (report->filename) {
         copy->filename = (const char*)cursor;
         js_memcpy(cursor, report->filename, filenameSize);
     }
     MOZ_ASSERT(cursor + filenameSize == (uint8_t*)copy + mallocSize);
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -4350,17 +4350,17 @@ LazyScript::CreateRaw(ExclusiveContext* 
     p.version = version;
     p.numFreeVariables = numFreeVariables;
     p.numInnerFunctions = numInnerFunctions;
     p.generatorKindBits = GeneratorKindAsBits(NotGenerator);
     p.strict = false;
     p.bindingsAccessedDynamically = false;
     p.hasDebuggerStatement = false;
     p.hasDirectEval = false;
-    p.usesArgumentsApplyAndThis = false;
+    p.isLikelyConstructorWrapper = false;
     p.isDerivedClassConstructor = false;
     p.needsHomeObject = false;
 
     LazyScript* res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, lineno, column);
     MOZ_ASSERT_IF(res, res->version() == version);
     return res;
 }
 
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1144,17 +1144,17 @@ class JSScript : public js::gc::TenuredC
 
     // Script came from eval(), and is still active.
     bool isActiveEval_:1;
 
     // Script came from eval(), and is in eval cache.
     bool isCachedEval_:1;
 
     // 'this', 'arguments' and f.apply() are used. This is likely to be a wrapper.
-    bool usesArgumentsApplyAndThis_:1;
+    bool isLikelyConstructorWrapper_:1;
 
     // IonMonkey compilation hints.
     bool failedBoundsCheck_:1; /* script has had hoisted bounds checks fail */
     bool failedShapeGuard_:1; /* script has had hoisted shape guard fail */
     bool hadFrequentBailouts_:1;
     bool hadOverflowBailout_:1;
     bool uninlineable_:1;    /* explicitly marked as uninlineable */
 
@@ -1407,20 +1407,20 @@ class JSScript : public js::gc::TenuredC
     void uncacheForEval() {
         MOZ_ASSERT(isCachedEval() && !isActiveEval());
         isCachedEval_ = false;
         isActiveEval_ = true;
     }
 
     void setActiveEval() { isActiveEval_ = true; }
 
-    bool usesArgumentsApplyAndThis() const {
-        return usesArgumentsApplyAndThis_;
+    bool isLikelyConstructorWrapper() const {
+        return isLikelyConstructorWrapper_;
     }
-    void setUsesArgumentsApplyAndThis() { usesArgumentsApplyAndThis_ = true; }
+    void setLikelyConstructorWrapper() { isLikelyConstructorWrapper_ = true; }
 
     bool isGeneratorExp() const { return isGeneratorExp_; }
 
     bool failedBoundsCheck() const {
         return failedBoundsCheck_;
     }
     bool failedShapeGuard() const {
         return failedShapeGuard_;
@@ -2174,17 +2174,17 @@ class LazyScript : public gc::TenuredCel
 
         // N.B. These are booleans but need to be uint32_t to pack correctly on MSVC.
         // If you add another boolean here, make sure to initialze it in
         // LazyScript::CreateRaw().
         uint32_t strict : 1;
         uint32_t bindingsAccessedDynamically : 1;
         uint32_t hasDebuggerStatement : 1;
         uint32_t hasDirectEval : 1;
-        uint32_t usesArgumentsApplyAndThis : 1;
+        uint32_t isLikelyConstructorWrapper : 1;
         uint32_t hasBeenCloned : 1;
         uint32_t treatAsRunOnce : 1;
         uint32_t isDerivedClassConstructor : 1;
         uint32_t needsHomeObject : 1;
     };
 
     union {
         PackedView p_;
@@ -2328,21 +2328,21 @@ class LazyScript : public gc::TenuredCel
 
     bool hasDirectEval() const {
         return p_.hasDirectEval;
     }
     void setHasDirectEval() {
         p_.hasDirectEval = true;
     }
 
-    bool usesArgumentsApplyAndThis() const {
-        return p_.usesArgumentsApplyAndThis;
+    bool isLikelyConstructorWrapper() const {
+        return p_.isLikelyConstructorWrapper;
     }
-    void setUsesArgumentsApplyAndThis() {
-        p_.usesArgumentsApplyAndThis = true;
+    void setLikelyConstructorWrapper() {
+        p_.isLikelyConstructorWrapper = true;
     }
 
     bool hasBeenCloned() const {
         return p_.hasBeenCloned;
     }
     void setHasBeenCloned() {
         p_.hasBeenCloned = true;
     }
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -285,17 +285,16 @@ UNIFIED_SOURCES += [
     'perf/jsperf.cpp',
     'proxy/BaseProxyHandler.cpp',
     'proxy/CrossCompartmentWrapper.cpp',
     'proxy/DeadObjectProxy.cpp',
     'proxy/DirectProxyHandler.cpp',
     'proxy/OpaqueCrossCompartmentWrapper.cpp',
     'proxy/Proxy.cpp',
     'proxy/ScriptedDirectProxyHandler.cpp',
-    'proxy/ScriptedIndirectProxyHandler.cpp',
     'proxy/SecurityWrapper.cpp',
     'proxy/Wrapper.cpp',
     'vm/ArgumentsObject.cpp',
     'vm/ArrayBufferObject.cpp',
     'vm/CallNonGenericMethod.cpp',
     'vm/CharacterEncoding.cpp',
     'vm/CodeCoverage.cpp',
     'vm/Compression.cpp',
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -12,17 +12,16 @@
 #include "jscntxt.h"
 #include "jsfun.h"
 #include "jsgc.h"
 #include "jswrapper.h"
 
 #include "gc/Marking.h"
 #include "proxy/DeadObjectProxy.h"
 #include "proxy/ScriptedDirectProxyHandler.h"
-#include "proxy/ScriptedIndirectProxyHandler.h"
 #include "vm/WrapperObject.h"
 
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
 
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
@@ -747,18 +746,16 @@ ProxyObject::renew(JSContext* cx, const 
     setExtra(0, UndefinedValue());
     setExtra(1, UndefinedValue());
 }
 
 JS_FRIEND_API(JSObject*)
 js::InitProxyClass(JSContext* cx, HandleObject obj)
 {
     static const JSFunctionSpec static_methods[] = {
-        JS_FN("create",         proxy_create,          2, 0),
-        JS_FN("createFunction", proxy_createFunction,  3, 0),
         JS_FN("revocable",      proxy_revocable,       2, 0),
         JS_FS_END
     };
 
     Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
     RootedFunction ctor(cx);
     ctor = global->createConstructor(cx, proxy, cx->names().Proxy, 2);
     if (!ctor)
deleted file mode 100644
--- a/js/src/proxy/ScriptedIndirectProxyHandler.cpp
+++ /dev/null
@@ -1,611 +0,0 @@
-/* -*- 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 "proxy/ScriptedIndirectProxyHandler.h"
-
-#include "jsapi.h"
-#include "jscntxt.h"
-
-#include "jscntxtinlines.h"
-#include "jsobjinlines.h"
-
-using namespace js;
-
-static bool
-GetFundamentalTrap(JSContext* cx, HandleObject handler, HandlePropertyName name,
-                   MutableHandleValue fvalp)
-{
-    JS_CHECK_RECURSION(cx, return false);
-
-    return GetProperty(cx, handler, handler, name, fvalp);
-}
-
-static bool
-GetDerivedTrap(JSContext* cx, HandleObject handler, HandlePropertyName name,
-               MutableHandleValue fvalp)
-{
-    MOZ_ASSERT(name == cx->names().has ||
-               name == cx->names().hasOwn ||
-               name == cx->names().get ||
-               name == cx->names().set ||
-               name == cx->names().keys ||
-               name == cx->names().iterate);
-
-    return GetProperty(cx, handler, handler, name, fvalp);
-}
-
-static bool
-Trap(JSContext* cx, HandleObject handler, HandleValue fval, unsigned argc, Value* argv,
-     MutableHandleValue rval)
-{
-    return Invoke(cx, ObjectValue(*handler), fval, argc, argv, rval);
-}
-
-static bool
-Trap1(JSContext* cx, HandleObject handler, HandleValue fval, HandleId id, MutableHandleValue rval)
-{
-    if (!IdToStringOrSymbol(cx, id, rval))
-        return false;
-    return Trap(cx, handler, fval, 1, rval.address(), rval);
-}
-
-static bool
-Trap2(JSContext* cx, HandleObject handler, HandleValue fval, HandleId id, Value v_,
-      MutableHandleValue rval)
-{
-    RootedValue v(cx, v_);
-    if (!IdToStringOrSymbol(cx, id, rval))
-        return false;
-    JS::AutoValueArray<2> argv(cx);
-    argv[0].set(rval);
-    argv[1].set(v);
-    return Trap(cx, handler, fval, 2, argv.begin(), rval);
-}
-
-static bool
-IndicatePropertyNotFound(MutableHandle<PropertyDescriptor> desc)
-{
-    desc.object().set(nullptr);
-    return true;
-}
-
-static bool
-ValueToBool(HandleValue v, bool* bp)
-{
-    *bp = ToBoolean(v);
-    return true;
-}
-
-static bool
-ArrayToIdVector(JSContext* cx, const Value& array, AutoIdVector& props)
-{
-    MOZ_ASSERT(props.length() == 0);
-
-    if (array.isPrimitive())
-        return true;
-
-    RootedObject obj(cx, &array.toObject());
-    uint32_t length;
-    if (!GetLengthProperty(cx, obj, &length))
-        return false;
-
-    RootedValue v(cx);
-    for (uint32_t n = 0; n < length; ++n) {
-        if (!CheckForInterrupt(cx))
-            return false;
-        if (!GetElement(cx, obj, obj, n, &v))
-            return false;
-        RootedId id(cx);
-        if (!ValueToId<CanGC>(cx, v, &id))
-            return false;
-        if (!props.append(id))
-            return false;
-    }
-
-    return true;
-}
-
-namespace {
-
-/*
- * Old-style indirect proxies allow callers to specify distinct scripted
- * [[Call]] and [[Construct]] traps. We use an intermediate object so that we
- * can stash this information in a single reserved slot on the proxy object.
- *
- * Note - Currently this is slightly unnecesary, because we actually have 2
- * extra slots, neither of which are used for ScriptedIndirectProxy. But we're
- * eventually moving towards eliminating one of those slots, and so we don't
- * want to add a dependency here.
- */
-static const Class CallConstructHolder = {
-    "CallConstructHolder",
-    JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS
-};
-
-} /* anonymous namespace */
-
-// This variable exists solely to provide a unique address for use as an identifier.
-const char ScriptedIndirectProxyHandler::family = 0;
-
-bool
-ScriptedIndirectProxyHandler::preventExtensions(JSContext* cx, HandleObject proxy,
-                                                ObjectOpResult& result) const
-{
-    // Scripted indirect proxies don't support extensibility changes.
-    return result.fail(JSMSG_CANT_CHANGE_EXTENSIBILITY);
-}
-
-bool
-ScriptedIndirectProxyHandler::isExtensible(JSContext* cx, HandleObject proxy,
-                                           bool* extensible) const
-{
-    // Scripted indirect proxies don't support extensibility changes.
-    *extensible = true;
-    return true;
-}
-
-static bool
-ReturnedValueMustNotBePrimitive(JSContext* cx, HandleObject proxy, JSAtom* atom, const Value& v)
-{
-    if (v.isPrimitive()) {
-        JSAutoByteString bytes;
-        if (AtomToPrintableString(cx, atom, &bytes)) {
-            RootedValue val(cx, ObjectOrNullValue(proxy));
-            ReportValueError2(cx, JSMSG_BAD_TRAP_RETURN_VALUE,
-                              JSDVG_SEARCH_STACK, val, nullptr, bytes.ptr());
-        }
-        return false;
-    }
-    return true;
-}
-
-static JSObject*
-GetIndirectProxyHandlerObject(JSObject* proxy)
-{
-    return proxy->as<ProxyObject>().private_().toObjectOrNull();
-}
-
-bool
-ScriptedIndirectProxyHandler::getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
-                                                    MutableHandle<PropertyDescriptor> desc) const
-{
-    RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
-    RootedValue fval(cx), value(cx);
-    return GetFundamentalTrap(cx, handler, cx->names().getPropertyDescriptor, &fval) &&
-           Trap1(cx, handler, fval, id, &value) &&
-           ((value.isUndefined() && IndicatePropertyNotFound(desc)) ||
-            (ReturnedValueMustNotBePrimitive(cx, proxy, cx->names().getPropertyDescriptor, value) &&
-             ObjectToCompletePropertyDescriptor(cx, proxy, value, desc)));
-}
-
-bool
-ScriptedIndirectProxyHandler::getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
-                                                       MutableHandle<PropertyDescriptor> desc) const
-{
-    RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
-    RootedValue fval(cx), value(cx);
-    return GetFundamentalTrap(cx, handler, cx->names().getOwnPropertyDescriptor, &fval) &&
-           Trap1(cx, handler, fval, id, &value) &&
-           ((value.isUndefined() && IndicatePropertyNotFound(desc)) ||
-            (ReturnedValueMustNotBePrimitive(cx, proxy, cx->names().getPropertyDescriptor, value) &&
-             ObjectToCompletePropertyDescriptor(cx, proxy, value, desc)));
-}
-
-bool
-ScriptedIndirectProxyHandler::defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
-                                             Handle<PropertyDescriptor> desc,
-                                             ObjectOpResult& result) const
-{
-    RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
-    RootedValue fval(cx), value(cx);
-    return GetFundamentalTrap(cx, handler, cx->names().defineProperty, &fval) &&
-           FromPropertyDescriptorToObject(cx, desc, &value) &&
-           Trap2(cx, handler, fval, id, value, &value) &&
-           result.succeed();
-}
-
-bool
-ScriptedIndirectProxyHandler::ownPropertyKeys(JSContext* cx, HandleObject proxy,
-                                              AutoIdVector& props) const
-{
-    RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
-    RootedValue fval(cx), value(cx);
-    return GetFundamentalTrap(cx, handler, cx->names().getOwnPropertyNames, &fval) &&
-           Trap(cx, handler, fval, 0, nullptr, &value) &&
-           ArrayToIdVector(cx, value, props);
-}
-
-bool
-ScriptedIndirectProxyHandler::delete_(JSContext* cx, HandleObject proxy, HandleId id,
-                                      ObjectOpResult& result) const
-{
-    RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
-    RootedValue fval(cx), value(cx);
-    if (!GetFundamentalTrap(cx, handler, cx->names().delete_, &fval))
-        return false;
-    if (!Trap1(cx, handler, fval, id, &value))
-        return false;
-
-    if (ToBoolean(value))
-        result.succeed();
-    else
-        result.fail(JSMSG_PROXY_DELETE_RETURNED_FALSE);
-    return true;
-}
-
-bool
-ScriptedIndirectProxyHandler::enumerate(JSContext* cx, HandleObject proxy,
-                                        MutableHandleObject objp) const
-{
-    // The hook that is called "enumerate" in the spec, used to be "iterate"
-    RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
-    RootedValue value(cx);
-    if (!GetDerivedTrap(cx, handler, cx->names().iterate, &value))
-        return false;
-    if (!IsCallable(value))
-        return BaseProxyHandler::enumerate(cx, proxy, objp);
-
-    RootedValue rval(cx);
-    if (!Trap(cx, handler, value, 0, nullptr, &rval))
-        return false;
-    if (!ReturnedValueMustNotBePrimitive(cx, proxy, cx->names().iterate, rval))
-        return false;
-    objp.set(&rval.toObject());
-    return true;
-}
-
-bool
-ScriptedIndirectProxyHandler::has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const
-{
-    RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
-    RootedValue fval(cx), value(cx);
-    if (!GetDerivedTrap(cx, handler, cx->names().has, &fval))
-        return false;
-    if (!IsCallable(fval))
-        return BaseProxyHandler::has(cx, proxy, id, bp);
-    return Trap1(cx, handler, fval, id, &value) &&
-           ValueToBool(value, bp);
-}
-
-bool
-ScriptedIndirectProxyHandler::hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const
-{
-    RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
-    RootedValue fval(cx), value(cx);
-    if (!GetDerivedTrap(cx, handler, cx->names().hasOwn, &fval))
-        return false;
-    if (!IsCallable(fval))
-        return BaseProxyHandler::hasOwn(cx, proxy, id, bp);
-    return Trap1(cx, handler, fval, id, &value) &&
-           ValueToBool(value, bp);
-}
-
-bool
-ScriptedIndirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleValue receiver,
-                                  HandleId id, MutableHandleValue vp) const
-{
-    RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
-    RootedValue idv(cx);
-    if (!IdToStringOrSymbol(cx, id, &idv))
-        return false;
-    JS::AutoValueArray<2> argv(cx);
-    argv[0].set(receiver);
-    argv[1].set(idv);
-    RootedValue fval(cx);
-    if (!GetDerivedTrap(cx, handler, cx->names().get, &fval))
-        return false;
-    if (!IsCallable(fval))
-        return derivedGet(cx, proxy, receiver, id, vp);
-    return Trap(cx, handler, fval, 2, argv.begin(), vp);
-}
-
-bool
-ScriptedIndirectProxyHandler::derivedGet(JSContext* cx, HandleObject proxy, HandleValue receiver,
-                                         HandleId id, MutableHandleValue vp) const
-{
-    // This uses getPropertyDescriptor for backward compatibility reasons.
-
-    Rooted<PropertyDescriptor> desc(cx);
-    if (!getPropertyDescriptor(cx, proxy, id, &desc))
-        return false;
-    desc.assertCompleteIfFound();
-
-    if (!desc.object()) {
-        vp.setUndefined();
-        return true;
-    }
-
-    if (desc.isDataDescriptor()) {
-        vp.set(desc.value());
-        return true;
-    }
-
-    MOZ_ASSERT(desc.isAccessorDescriptor());
-    RootedObject getter(cx, desc.getterObject());
-
-    if (!getter) {
-        vp.setUndefined();
-        return true;
-    }
-
-    return InvokeGetter(cx, receiver, ObjectValue(*getter), vp);
-}
-
-bool
-ScriptedIndirectProxyHandler::set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
-                                  HandleValue receiver, ObjectOpResult& result) const
-{
-    RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
-    RootedValue idv(cx);
-    if (!IdToStringOrSymbol(cx, id, &idv))
-        return false;
-    JS::AutoValueArray<3> argv(cx);
-    argv[0].set(receiver);
-    argv[1].set(idv);
-    argv[2].set(v);
-    RootedValue fval(cx);
-    if (!GetDerivedTrap(cx, handler, cx->names().set, &fval))
-        return false;
-    if (!IsCallable(fval))
-        return derivedSet(cx, proxy, id, v, receiver, result);
-    if (!Trap(cx, handler, fval, 3, argv.begin(), &idv))
-        return false;
-    return result.succeed();
-}
-
-static bool
-CallSetter(JSContext* cx, HandleValue receiver, HandleId id, SetterOp op, unsigned attrs,
-           HandleValue v, ObjectOpResult& result)
-{
-    if (attrs & JSPROP_SETTER) {
-        RootedValue fval(cx, CastAsObjectJsval(op));
-        if (!InvokeSetter(cx, receiver, fval, v))
-            return false;
-        return result.succeed();
-    }
-
-    if (attrs & JSPROP_GETTER)
-        return result.fail(JSMSG_GETTER_ONLY);
-
-    if (!receiver.isObject())
-        return result.fail(JSMSG_SET_NON_OBJECT_RECEIVER);
-    RootedObject receiverObj(cx, &receiver.toObject());
-
-    if (!op)
-        return result.succeed();
-
-    RootedValue valCopy(cx, v);
-    return CallJSSetterOp(cx, op, receiverObj, id, &valCopy, result);
-}
-
-bool
-ScriptedIndirectProxyHandler::derivedSet(JSContext* cx, HandleObject proxy, HandleId id,
-                                         HandleValue v, HandleValue receiver,
-                                         ObjectOpResult& result) const
-{
-    // Find an own or inherited property. The code here is strange for maximum
-    // backward compatibility with earlier code written before ES6 and before
-    // SetPropertyIgnoringNamedGetter.
-    //
-    // As of March 2015, testing/specialpowers/content/specialpowersAPI.js
-    // depends on the call to getPropertyDescriptor below, because it does
-    // support inherited setters but makes no attempt to provide a meaningful
-    // prototype chain.
-
-    Rooted<PropertyDescriptor> desc(cx);
-    if (!getOwnPropertyDescriptor(cx, proxy, id, &desc))
-        return false;
-    bool descIsOwn = desc.object() != nullptr;
-    if (!descIsOwn) {
-        if (!getPropertyDescriptor(cx, proxy, id, &desc))
-            return false;
-    }
-
-    MOZ_ASSERT_IF(descIsOwn, desc.object());
-    if (desc.object()) {
-        MOZ_ASSERT(desc.getter() != JS_PropertyStub);
-        MOZ_ASSERT(desc.setter() != JS_StrictPropertyStub);
-
-        // Check for read-only properties.
-        if (desc.isDataDescriptor() && !desc.writable())
-            return result.fail(descIsOwn ? JSMSG_READ_ONLY : JSMSG_CANT_REDEFINE_PROP);
-
-        if (desc.hasSetterObject() || desc.setter()) {
-            if (!CallSetter(cx, receiver, id, desc.setter(), desc.attributes(), v, result))
-                return false;
-            if (!result)
-                return true;
-            if (!proxy->is<ProxyObject>() ||
-                proxy->as<ProxyObject>().handler() != this ||
-                desc.isShared())
-            {
-                return result.succeed();
-            }
-        }
-        desc.value().set(v);
-
-        if (descIsOwn) {
-            MOZ_ASSERT(desc.object() == proxy);
-            return this->defineProperty(cx, proxy, id, desc, result);
-        }
-    } else {
-        desc.setDataDescriptor(v, JSPROP_ENUMERATE);
-    }
-
-    if (!receiver.isObject())
-        return result.fail(JSMSG_SET_NON_OBJECT_RECEIVER);
-    RootedObject receiverObj(cx, &receiver.toObject());
-    return DefineProperty(cx, receiverObj, id, desc, result);
-}
-
-bool
-ScriptedIndirectProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
-                                                           AutoIdVector& props) const
-{
-    RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
-    RootedValue value(cx);
-    if (!GetDerivedTrap(cx, handler, cx->names().keys, &value))
-        return false;
-    if (!IsCallable(value))
-        return BaseProxyHandler::getOwnEnumerablePropertyKeys(cx, proxy, props);
-    return Trap(cx, handler, value, 0, nullptr, &value) &&
-           ArrayToIdVector(cx, value, props);
-}
-
-bool
-ScriptedIndirectProxyHandler::nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
-                                         const CallArgs& args) const
-{
-    return BaseProxyHandler::nativeCall(cx, test, impl, args);
-}
-
-JSString*
-ScriptedIndirectProxyHandler::fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const
-{
-    assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
-    if (!proxy->isCallable()) {
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
-                             JSMSG_INCOMPATIBLE_PROTO,
-                             js_Function_str, js_toString_str,
-                             "object");
-        return nullptr;
-    }
-    RootedObject obj(cx, &proxy->as<ProxyObject>().extra(0).toObject().as<NativeObject>().getReservedSlot(0).toObject());
-    return fun_toStringHelper(cx, obj, indent);
-}
-
-const ScriptedIndirectProxyHandler ScriptedIndirectProxyHandler::singleton;
-
-bool
-CallableScriptedIndirectProxyHandler::call(JSContext* cx, HandleObject proxy, const CallArgs& args) const
-{
-    assertEnteredPolicy(cx, proxy, JSID_VOID, CALL);
-    RootedObject ccHolder(cx, &proxy->as<ProxyObject>().extra(0).toObject());
-    MOZ_ASSERT(ccHolder->getClass() == &CallConstructHolder);
-    RootedValue call(cx, ccHolder->as<NativeObject>().getReservedSlot(0));
-    MOZ_ASSERT(call.isObject() && call.toObject().isCallable());
-    return Invoke(cx, args.thisv(), call, args.length(), args.array(), args.rval());
-}
-
-bool
-CallableScriptedIndirectProxyHandler::construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const
-{
-    assertEnteredPolicy(cx, proxy, JSID_VOID, CALL);
-
-    RootedObject ccHolder(cx, &proxy->as<ProxyObject>().extra(0).toObject());
-    MOZ_ASSERT(ccHolder->getClass() == &CallConstructHolder);
-
-    RootedValue construct(cx, ccHolder->as<NativeObject>().getReservedSlot(1));
-
-    // We could enforce this at proxy creation time, but lipstick on a pig.
-    // Plus, let's delay in-the-field bustage as long as possible.
-    if (!IsConstructor(construct)) {
-        ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, construct, nullptr);
-        return false;
-    }
-
-    ConstructArgs cargs(cx);
-    if (!FillArgumentsFromArraylike(cx, cargs, args))
-        return false;
-
-    RootedObject obj(cx);
-    if (!Construct(cx, construct, cargs, args.newTarget(), &obj))
-        return false;
-
-    args.rval().setObject(*obj);
-    return true;
-}
-
-const CallableScriptedIndirectProxyHandler CallableScriptedIndirectProxyHandler::singleton;
-
-bool
-js::proxy_create(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-
-    RootedObject create(cx, &args.callee());
-    if (!GlobalObject::warnOnceAboutProxyCreate(cx, create))
-        return false;
-
-    if (args.length() < 1) {
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
-                             "create", "0", "s");
-        return false;
-    }
-    JSObject* handler = NonNullObject(cx, args[0]);
-    if (!handler)
-        return false;
-    JSObject* proto;
-    if (args.get(1).isObject()) {
-        proto = &args[1].toObject();
-    } else {
-        MOZ_ASSERT(IsFunctionObject(&args.callee()));
-        proto = nullptr;
-    }
-    RootedValue priv(cx, ObjectValue(*handler));
-    JSObject* proxy = NewProxyObject(cx, &ScriptedIndirectProxyHandler::singleton,
-                                     priv, proto);
-    if (!proxy)
-        return false;
-
-    args.rval().setObject(*proxy);
-    return true;
-}
-
-bool
-js::proxy_createFunction(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-
-    RootedObject createFunction(cx, &args.callee());
-    if (!GlobalObject::warnOnceAboutProxyCreate(cx, createFunction))
-        return false;
-
-    if (args.length() < 2) {
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
-                             "createFunction", "1", "");
-        return false;
-    }
-    RootedObject handler(cx, NonNullObject(cx, args[0]));
-    if (!handler)
-        return false;
-    RootedObject proto(cx, args.callee().global().getOrCreateFunctionPrototype(cx));
-    if (!proto)
-        return false;
-
-    RootedObject call(cx, ValueToCallable(cx, args[1], args.length() - 2));
-    if (!call)
-        return false;
-    RootedObject construct(cx, nullptr);
-    if (args.length() > 2) {
-        construct = ValueToCallable(cx, args[2], args.length() - 3);
-        if (!construct)
-            return false;
-    } else {
-        construct = call;
-    }
-
-    // Stash the call and construct traps on a holder object that we can stick
-    // in a slot on the proxy.
-    RootedObject ccHolder(cx, JS_NewObjectWithGivenProto(cx, Jsvalify(&CallConstructHolder),
-                                                         nullptr));
-    if (!ccHolder)
-        return false;
-    ccHolder->as<NativeObject>().setReservedSlot(0, ObjectValue(*call));
-    ccHolder->as<NativeObject>().setReservedSlot(1, ObjectValue(*construct));
-
-    RootedValue priv(cx, ObjectValue(*handler));
-    JSObject* proxy =
-        NewProxyObject(cx, &CallableScriptedIndirectProxyHandler::singleton,
-                       priv, proto);
-    if (!proxy)
-        return false;
-    proxy->as<ProxyObject>().setExtra(0, ObjectValue(*ccHolder));
-
-    args.rval().setObject(*proxy);
-    return true;
-}
deleted file mode 100644
--- a/js/src/proxy/ScriptedIndirectProxyHandler.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* -*- 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/. */
-
-#ifndef proxy_ScriptedIndirectProxyHandler_h
-#define proxy_ScriptedIndirectProxyHandler_h
-
-#include "js/Proxy.h"
-
-namespace js {
-
-/* Derived class for all scripted indirect proxy handlers. */
-class ScriptedIndirectProxyHandler : public BaseProxyHandler
-{
-  public:
-    MOZ_CONSTEXPR ScriptedIndirectProxyHandler()
-      : BaseProxyHandler(&family)
-    { }
-
-    /* Standard internal methods. */
-    virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
-                                          MutableHandle<PropertyDescriptor> desc) const override;
-    virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
-                                Handle<PropertyDescriptor> desc,
-                                ObjectOpResult& result) const override;
-    virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
-                                 AutoIdVector& props) const override;
-    virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
-                         ObjectOpResult& result) const override;
-    virtual bool enumerate(JSContext* cx, HandleObject proxy,
-                           MutableHandleObject objp) const override;
-    virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
-                                   ObjectOpResult& result) const override;
-    virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
-    virtual bool has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
-    virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver, HandleId id,
-                     MutableHandleValue vp) const override;
-    virtual bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
-                     HandleValue receiver, ObjectOpResult& result) const override;
-
-    /* SpiderMonkey extensions. */
-    virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
-                                       MutableHandle<PropertyDescriptor> desc) const override;
-    virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
-    virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
-                                              AutoIdVector& props) const override;
-    virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
-                            const CallArgs& args) const override;
-    virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const override;
-    virtual bool isScripted() const override { return true; }
-
-    static const char family;
-    static const ScriptedIndirectProxyHandler singleton;
-
-private:
-    bool derivedGet(JSContext* cx, HandleObject proxy, HandleValue receiver, HandleId id,
-                    MutableHandleValue vp) const;
-    bool derivedSet(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
-                    HandleValue receiver, ObjectOpResult& result) const;
-};
-
-/* Derived class to handle Proxy.createFunction() */
-class CallableScriptedIndirectProxyHandler : public ScriptedIndirectProxyHandler
-{
-  public:
-    CallableScriptedIndirectProxyHandler() : ScriptedIndirectProxyHandler() { }
-    virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
-    virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
-
-    virtual bool isCallable(JSObject* obj) const override {
-        return true;
-    }
-    virtual bool isConstructor(JSObject* obj) const override {
-        return true;
-    }
-
-    static const CallableScriptedIndirectProxyHandler singleton;
-};
-
-bool
-proxy_create(JSContext* cx, unsigned argc, Value* vp);
-
-bool
-proxy_createFunction(JSContext* cx, unsigned argc, Value* vp);
-
-} /* namespace js */
-
-#endif /* proxy_ScriptedIndirectProxyHandler_h */
deleted file mode 100644
--- a/js/src/tests/ecma_5/extensions/proxy-__proto__.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-var gTestfile = 'proxy-__proto__.js';
-var BUGNUMBER = 770344;
-var summary = "Behavior of __proto__ on proxies";
-
-print(BUGNUMBER + ": " + summary);
-
-/**************
- * BEGIN TEST *
- **************/
-
-var protoDesc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
-var protoGetter = protoDesc.get;
-var protoSetter = protoDesc.set;
-
-function pp(arr)
-{
-  return arr.map(function(v) { return "" + v; }).join(", ");
-}
-
-function testProxy(creator, args, proto)
-{
-  print("Now testing behavior for " +
-        "Proxy." + creator + "(" + pp(args) + ")");
-
-  var pobj = Proxy[creator].apply(Proxy, args);
-
-  // Check [[Prototype]] before attempted mutation
-  assertEq(Object.getPrototypeOf(pobj), proto);
-  assertEq(protoGetter.call(pobj), proto);
-
-  // Attempt [[Prototype]] mutation
-  protoSetter.call(pobj, null);
-
-  // Check [[Prototype]] after attempted mutation
-  assertEq(Object.getPrototypeOf(pobj), null);
-  assertEq(protoGetter.call(pobj), null);
-}
-
-// Proxy object with non-null [[Prototype]]
-var nonNullProto = { toString: function() { return "non-null prototype"; } };
-var nonNullHandler = { toString: function() { return "non-null handler"; } };
-testProxy("create", [nonNullHandler, nonNullProto], nonNullProto);
-
-// Proxy object with null [[Prototype]]
-var nullProto = null;
-var nullHandler = { toString: function() { return "null handler"; } };
-testProxy("create", [nullHandler, nullProto], nullProto);
-
-// Proxy function with [[Call]]
-var callForCallOnly = function () { };
-callForCallOnly.toString = function() { return "callForCallOnly"; };
-var callOnlyHandler = { toString: function() { return "call-only handler"; } };
-testProxy("createFunction",
-          [callOnlyHandler, callForCallOnly], Function.prototype);
-
-// Proxy function with [[Call]] and [[Construct]]
-var callForCallConstruct = function() { };
-callForCallConstruct.toString = function() { return "call/construct call"; };
-var constructForCallConstruct = function() { };
-constructForCallConstruct.toString =
-  function() { return "call/construct construct"; };
-var handlerForCallConstruct =
-  { toString: function() { return "call/construct handler"; } };
-testProxy("createFunction",
-          [handlerForCallConstruct,
-           callForCallConstruct,
-           constructForCallConstruct],
-          Function.prototype);
-
-
-/******************************************************************************/
-
-if (typeof reportCompare === "function")
-  reportCompare(true, true);
-
-print("Tests complete");
--- a/js/src/tests/ecma_5/extensions/proxy-strict.js
+++ b/js/src/tests/ecma_5/extensions/proxy-strict.js
@@ -1,12 +1,12 @@
 /*
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/licenses/publicdomain/
  */
 
 var s = "grape";
 function f() { "use strict"; return this; }
-var p = Proxy.createFunction(f, f);
+var p = new Proxy(f, {});
 String.prototype.p = p;
 assertEq(s.p(), "grape");
 
 reportCompare(true,true);
--- a/js/src/tests/ecma_5/misc/new-with-non-constructor.js
+++ b/js/src/tests/ecma_5/misc/new-with-non-constructor.js
@@ -3,42 +3,30 @@
  * http://creativecommons.org/licenses/publicdomain/
  */
 
 function checkConstruct(thing) {
     try {
         new thing();
         assertEq(0, 1, "not reached " + thing);
     } catch (e) {
-        assertEq(String(e.message).indexOf(" is not a constructor") === -1, false);
+        assertEq(e.message.includes(" is not a constructor") ||
+                 e.message === "Function.prototype.toString called on incompatible object", true);
     }
 }
 
 var re = /aaa/
 checkConstruct(re);
 
 var boundFunctionPrototype = Function.prototype.bind();
 checkConstruct(boundFunctionPrototype);
 
 var boundBuiltin = Math.sin.bind();
 checkConstruct(boundBuiltin);
 
-/* We set the proxies construct trap to undefined,
- * so the call trap is used as constructor.
- */
-
-var handler = {
-    getPropertyDescriptor(name) {
-        /* toSource may be called to generate error message. */
-        assertEq(name, "toSource");
-        return { value: () => "foo" };
-    }
-};
-
-var proxiedFunctionPrototype = Proxy.create(handler, Function.prototype, undefined);
+var proxiedFunctionPrototype = new Proxy(Function.prototype, {});
 checkConstruct(proxiedFunctionPrototype);
 
-var proxiedBuiltin = Proxy.create(handler, parseInt, undefined);
+var proxiedBuiltin = new Proxy(parseInt, {});
 checkConstruct(proxiedBuiltin);
 
-
 if (typeof reportCompare == 'function')
     reportCompare(0, 0, "ok");
deleted file mode 100644
--- a/js/src/tests/ecma_6/extensions/indirect-proxy-preventExtensions-error-realm.js
+++ /dev/null
@@ -1,75 +0,0 @@
-// |reftest| skip-if(!xulRuntime.shell) -- needs newGlobal()
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-var gTestfile = "indirect-proxy-preventExtensions-error-realm.js";
-var BUGNUMBER = 1085566;
-var summary =
-  "The preventExtensions trap should return success/failure (with the " +
-  "outermost preventExtension caller deciding what to do in response), " +
-  "rather than throwing a TypeError itself";
-
-print(BUGNUMBER + ": " + summary);
-
-/**************
- * BEGIN TEST *
- **************/
-
-var g = newGlobal();
-
-// Someday indirect proxies will be thrown into the lake of fire and sulfur
-// alongside the beast and the false prophet, to be tormented day and night for
-// ever and ever.  When that happens, this test will need to be updated.
-//
-// The requirements for |p| are that 1) it be a cross-compartment wrapper, 2) to
-// a proxy, 3) whose C++ preventExtensions handler method returns true while
-// setting |*succeeded = false|.  The other options when this test was written)
-// were a global scope polluter (WindowNamedPropertiesHandler), a window object
-// (nsOuterWindowProxy), a DOM proxy (DOMProxyHandler), a SecurityWrapper, a
-// DebugScopeProxy (seemingly never directly exposed to script), and an
-// XrayWrapper.  Sadly none of these are simply available in both shell and
-// browser, so indirect proxies are it.
-//
-// (The other option would be to do this with a jsapi-test that defines a custom
-// proxy, but this was easier to write.  Maybe in the future, if no other such
-// proxies arise before indirect proxies die.)
-var p = g.Proxy.create({}, {});
-
-try
-{
-  // What we expect to happen is this:
-  //
-  //   * Object.preventExtensions delegates to
-  //   * cross-compartment wrapper preventExtensions trap, which delegates to
-  //   * indirect proxy preventExtensions trap, which sets |*succeeded = false|
-  //     *and does not throw or return false (in the JSAPI sense)*
-  //
-  // Returning false does not immediately create an error.  Instead that bubbles
-  // backward through the layers to the initial [[PreventExtensions]] call, made
-  // by Object.preventExtensions.  That function then creates and throws a
-  // TypeError in response to that false result -- from its realm, not from the
-  // indirect proxy's realm.
-  Object.preventExtensions(p);
-
-  throw new Error("didn't throw at all");
-}
-catch (e)
-{
-  assertEq(e instanceof TypeError, true,
-           "expected a TypeError from this global, instead got " + e +
-           ", from " +
-           (e.constructor === TypeError
-            ? "this global"
-            : e.constructor === g.TypeError
-            ? "the proxy's global"
-            : "somewhere else (!!!)"));
-}
-
-/******************************************************************************/
-
-if (typeof reportCompare === "function")
-  reportCompare(true, true);
-
-print("Tests complete");
--- a/js/src/tests/ecma_6/extensions/setImmutablePrototype.js
+++ b/js/src/tests/ecma_6/extensions/setImmutablePrototype.js
@@ -175,28 +175,16 @@ function runNormalTests(global)
     throw new Error("expected to throw on another revoked proxy, returned " + rv);
   }
   catch (e)
   {
     // NOTE: Again from |global|, as above.
     assertEq(e instanceof global.TypeError, true,
              "expected TypeError, instead threw " + e);
   }
-
-  // hated indirect proxies
-  var oldProto = {};
-  var indirectProxy = global.Proxy.create({}, oldProto);
-  assertEq(setImmutablePrototype(indirectProxy), true);
-  assertEq(Object.getPrototypeOf(indirectProxy), oldProto);
-  checkPrototypeMutationFailure(indirectProxy, "indirectProxy");
-
-  var indirectFunctionProxy = global.Proxy.createFunction({}, function call() {});
-  assertEq(setImmutablePrototype(indirectFunctionProxy), true);
-  assertEq(Object.getPrototypeOf(indirectFunctionProxy), global.Function.prototype);
-  checkPrototypeMutationFailure(indirectFunctionProxy, "indirectFunctionProxy");
 }
 
 var global = this;
 runNormalTests(global); // same-global
 
 if (typeof newGlobal === "function")
 {
   var otherGlobal = newGlobal();
--- a/js/src/tests/js1_8_5/extensions/clone-errors.js
+++ b/js/src/tests/js1_8_5/extensions/clone-errors.js
@@ -12,14 +12,14 @@ function check(v) {
     throw new Error("serializing " + uneval(v) + " should have failed with an exception");
 }
 
 // Unsupported object types.
 check(new Error("oops"));
 check(this);
 check(Math);
 check(function () {});
-check(Proxy.create({enumerate: function () { return []; }}));
+check(new Proxy({}, {}));
 
 // A failing getter.
 check({get x() { throw new Error("fail"); }});
 
 reportCompare(0, 0, "ok");
deleted file mode 100644
--- a/js/src/tests/js1_8_5/extensions/correct-this-for-nonnatives-on-array-proto-chain.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// Any copyright is dedicated to the Public Domain.
-// http://creativecommons.org/licenses/publicdomain/
-
-//-----------------------------------------------------------------------------
-var BUGNUMBER = 699705;
-var summary =
-  "When getting a property from a dense array that lives on the proto chain "+
-  "and in particular lives on a non-native object, we should still invoke "+
-  "property getter";
-
-print(BUGNUMBER + ": " + summary);
-
-/**************
- * BEGIN TEST *
- **************/
-
-var protoArr = Proxy.create({
-    getOwnPropertyDescriptor: function(name) {
-        if (name == "foo") return { get: function() { return this[0]; } };
-        return (void 0);
-    },
-    getPropertyDescriptor: function(name) {
-        return this.getOwnPropertyDescriptor(name);
-    },
-}, null);
-void (Array.prototype.__proto__ = protoArr);
-var testArr = [ "PASS" ];
-// Make sure we don't optimize the get to a .foo get, so do the dance
-// with passing in a string.
-function f(name) {
-    return testArr[name];
-}
-var propValue = f("foo");
-assertEq(propValue, "PASS",
-	 "expected to get 'PASS' out of the getter, got: " + propValue);
-
-/******************************************************************************/
-
-if (typeof reportCompare === "function")
-  reportCompare(true, true);
-
-print("All tests passed!");
deleted file mode 100644
--- a/js/src/tests/js1_8_5/extensions/proxy-fix.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// |reftest| skip
-// Any copyright is dedicated to the Public Domain.
-// http://creativecommons.org/licenses/publicdomain/
-// Contributor: Josh Matthews
-
-var p = Proxy.create({ fix: function() { return {foo: {value: 2} }; } });
-Object.preventExtensions(p);
-reportCompare(p.foo, 2, "property exists");
-p.foo = 3;
-reportCompare(p.foo, 2, "proxy is frozen");
\ No newline at end of file
deleted file mode 100644
--- a/js/src/tests/js1_8_5/extensions/scripted-proxies.js
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- * Contributor: Andreas Gal
- */
-
-//-----------------------------------------------------------------------------
-var BUGNUMBER = 546590;
-var summary = 'basic scripted proxies tests';
-var actual = '';
-var expect = '';
-
-//-----------------------------------------------------------------------------
-test();
-//-----------------------------------------------------------------------------
-
-function test() {
-    enterFunc ('test');
-    printBugNumber(BUGNUMBER);
-    printStatus(summary);
-
-    testObj({ foo: 1, bar: 2 });
-    testObj({ 1: 2, 3: 4 });
-    testObj([ 1, 2, 3 ]);
-    testObj(new Date());
-    testObj(new Array());
-    testObj(new RegExp());
-    testObj(Date);
-    testObj(Array);
-    testObj(RegExp);
-
-    /* Test function proxies. */
-    var proxy = Proxy.createFunction({
-        get: function(obj, name) {
-            return Function.prototype[name];
-        },
-        getOwnPropertyDescriptor: function(obj, name) {
-            return Object.getOwnPropertyDescriptor(Function.prototype, name);
-        },
-        fix: function() {
-            return ({});
-        }
-    }, function() { return "call"; });
-
-    assertEq(proxy(), "call");
-    assertEq(Function.prototype.bind.call(proxy)(), "call");
-    assertEq(typeof proxy, "function");
-    if ("isTrapping" in Proxy) {
-	assertEq(Proxy.isTrapping(proxy), true);
-	assertEq(Proxy.fix(proxy), true);
-	assertEq(Proxy.isTrapping(proxy), false);
-	assertEq(typeof proxy, "function");
-	assertEq(proxy(), "call");
-    }
-
-    /* Test function proxies as constructors. */
-    var proxy = Proxy.createFunction({
-        get: function(obj, name) {
-            return Function.prototype[name];
-        },
-        getOwnPropertyDescriptor: function(obj, name) {
-            return Object.getOwnPropertyDescriptor(Function.prototype, name);
-        },
-        fix: function() {
-            return ({});
-        }
-    },
-    function() { var x = {}; x.origin = "call"; return x; },
-    function() { var x = {}; x.origin = "new"; return x; })
-
-    assertEq(proxy().origin, "call");
-    assertEq(Function.prototype.bind.call(proxy)().origin, "call");
-    assertEq((new proxy()).origin, "new");
-    assertEq(new (Function.prototype.bind.call(proxy))().origin, "new");
-    if ("fix" in Proxy) {
-	assertEq(Proxy.fix(proxy), true);
-	assertEq(proxy().origin, "call");
-	assertEq((new proxy()).origin, "new");
-    }
-
-    /* Test fallback on call if no construct trap was given. */
-    var proxy = Proxy.createFunction({
-        get: function(obj, name) { return Function.prototype[name]; },
-        fix: function() { return ({}); }
-    },
-    function() { this.origin = "new"; return "new-ret"; });
-
-    assertEq((new proxy()).origin, "new");
-    if ("fix" in Proxy) {
-        assertEq(Proxy.fix(proxy), true);
-        assertEq((new proxy()).origin, "new");
-    }
-
-    /* Test invoke. */
-    var proxy = Proxy.create({ get: function(obj,name) { return function(a,b,c) { return name + uneval([a,b,c]); } }});
-    assertEq(proxy.foo(1,2,3), "foo[1, 2, 3]");
-
-    reportCompare(0, 0, "done.");
-
-    exitFunc ('test');
-}
-
-/* Test object proxies. */
-function noopHandlerMaker(obj) {
-    return {
-	getOwnPropertyDescriptor: function(name) {
-	    var desc = Object.getOwnPropertyDescriptor(obj);
-	    // a trapping proxy's properties must always be configurable
-	    desc.configurable = true;
-	    return desc;
-	},
-	getPropertyDescriptor: function(name) {
-	    var desc = Object.getPropertyDescriptor(obj); // assumed
-	    // a trapping proxy's properties must always be configurable
-	    desc.configurable = true;
-	    return desc;
-	},
-	getOwnPropertyNames: function() {
-	    return Object.getOwnPropertyNames(obj);
-	},
-	defineProperty: function(name, desc) {
-	    return Object.defineProperty(obj, name, desc);
-	},
-	delete: function(name) { return delete obj[name]; },
-	fix: function() {
-	    // As long as obj is not frozen, the proxy won't allow itself to be fixed
-	    // if (!Object.isFrozen(obj)) [not implemented in SpiderMonkey]
-	    //     return undefined;
-	    // return Object.getOwnProperties(obj); // assumed [not implemented in SpiderMonkey]
-	    var props = {};
-	    for (x in obj)
-		props[x] = Object.getOwnPropertyDescriptor(obj, x);
-	    return props;
-	},
- 	has: function(name) { return name in obj; },
-	hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
-	get: function(receiver, name) { return obj[name]; },
-	set: function(receiver, name, val) { obj[name] = val; return true; }, // bad behavior when set fails in non-strict mode
-	enumerate: function() {
-	    var result = [];
-	    for (name in obj) { result.push(name); };
-	    return result;
-	},
-	keys: function() { return Object.keys(obj); }
-    };
-};
-
-function testNoopHandler(obj, proxy) {
-    /* Check that both objects see the same properties. */
-    for (x in obj)
-	assertEq(obj[x], proxy[x]);
-    for (x in proxy)
-	assertEq(obj[x], proxy[x]);
-    /* Check that the iteration order is the same. */
-    var a = [], b = [];
-    for (x in obj)
-	a.push(x);
-    for (x in proxy)
-	b.push(x);
-    assertEq(uneval(a), uneval(b));
-}
-
-function testObj(obj) {
-    var proxy = Proxy.create(noopHandlerMaker(obj));
-    testNoopHandler(obj, proxy);
-    assertEq(typeof proxy, "object");
-    if ("isTrapping" in Proxy) {
-	assertEq(Proxy.isTrapping(proxy), true);
-	assertEq(Proxy.fix(proxy), true);
-	assertEq(Proxy.isTrapping(proxy), false);
-	assertEq(typeof proxy, "object");
-	testNoopHandler(obj, proxy);
-    }
-}
deleted file mode 100644
--- a/js/src/tests/js1_8_5/regress/regress-566914.js
+++ /dev/null
@@ -1,21 +0,0 @@
-function f(code) {
-	    code.replace(/s/, "")
-	    eval(code)
-	}
-	this.__defineGetter__("x", function() { return /x/.exec('x'); })
-	f("function a() {\
-	    x = Proxy.createFunction((function () {\
-	        return {\
-defineProperty:	 function (name, desc) {\
-	                Object.defineProperty(x, name, desc)\
-	            },\
-has:	 function () {},\
-get:	 function (r, name) {\
-	                return x[name]\
-	            }\
-	        }\
-	    })(), Object.defineProperties).__defineGetter__(\"\",(Function(\"\")))} ;\
-	a()\
-	")
-
-reportCompare("ok", "ok", "bug 566914");
deleted file mode 100644
--- a/js/src/tests/js1_8_5/regress/regress-584578.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// |reftest| skip
-// Any copyright is dedicated to the Public Domain.
-// http://creativecommons.org/licenses/publicdomain/
-// Contributor: Jesse Ruderman <jruderman@gmail.com>
-
-try {
-  var x = Proxy.create( {get:function(r,name){return {}[name]}} );
-  x.watch('e', function(){});
-} catch (exc) {
-}
-
-reportCompare(0, 0, 'ok');
deleted file mode 100644
--- a/js/src/tests/js1_8_5/regress/regress-595230-1.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// |reftest| fails-if(!xulRuntime.shell)
-// Any copyright is dedicated to the Public Domain.
-// http://creativecommons.org/licenses/publicdomain/
-// Contributors: Gary Kwong <gary@rumblingedge.com>, Brendan Eich <brendan@mozilla.com>
-
-var box = evalcx('lazy');
-
-var src =
-    'try {\n' +
-    '    __proto__ = Proxy.createFunction((function() {}), function() {})\n' +
-    '    var x\n' +
-    '    {}\n' +
-    '} catch(e) {}\n' +
-    'for (let b in [0, 0]) {}\n' +
-    '0\n';
-
-evalcx(src, box);
-
-this.reportCompare(0, 0, "ok");
deleted file mode 100644
--- a/js/src/tests/js1_8_5/regress/regress-618574.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// |reftest| skip
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- * Contributors: Gary Kwong and Jason Orendorff
- */
-
-var x = Proxy.create({
-    iterate: function () {
-            function f(){}
-            f.next = function () { throw StopIteration; }
-            return f;
-        }
-    });
-
-for each (var e in [{}, {}, {}, {}, {}, {}, {}, {}, x]) {
-    for (var v in e)  // do not assert
-        ;
-}
-
-reportCompare(0, 0, 'ok');
--- a/js/src/tests/js1_8_5/regress/regress-620376-1.js
+++ b/js/src/tests/js1_8_5/regress/regress-620376-1.js
@@ -5,17 +5,17 @@
  * Contributors: Igor Bukanov
  */
 
 // Test that we can terminate looping array enumeration
 function test() {
     if (typeof timeout != "function")
 	return;
 
-    var p = Proxy.create({ keys: function() { return Array(1e9); }});
+    var p = new Proxy({}, { onwKeys: function() { return Array(1e9); }});
 
     expectExitCode(6);
     timeout(0.001);
 
     var n = 0;
     for (i in p) { ++n;}
     return n;
 }
deleted file mode 100644
--- a/js/src/tests/js1_8_5/regress/regress-620376-2.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- * Contributors: Igor Bukanov
- */
-
-function test() {
-    var p = Proxy.create({ keys: function() { return { get length() { throw 1; }}; }});
-
-    try {
-	for (i in p);
-	throw new Error("an exception should be thrown");
-    } catch (e) {
-	assertEq(e, 1);
-    }
-}
-
-test();
-reportCompare(0, 0, "ok");
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -132,17 +132,16 @@ class GlobalObject : public NativeObject
      */
     static_assert(JSCLASS_GLOBAL_SLOT_COUNT == RESERVED_SLOTS,
                   "global object slot counts are inconsistent");
 
     enum WarnOnceFlag : int32_t {
         WARN_WATCH_DEPRECATED                   = 1 << 0,
         WARN_PROTO_SETTING_SLOW                 = 1 << 1,
         WARN_STRING_CONTAINS_DEPRECATED         = 1 << 2,
-        WARN_PROXY_CREATE_DEPRECATED            = 1 << 3,
     };
 
     // Emit the specified warning if the given slot in |obj|'s global isn't
     // true, then set the slot to true.  Thus calling this method warns once
     // for each global object it's called on, and every other call does
     // nothing.
     static bool
     warnOnceAbout(JSContext* cx, HandleObject obj, WarnOnceFlag flag, unsigned errorNumber);
@@ -707,22 +706,16 @@ class GlobalObject : public NativeObject
     }
 
     // Warn about use of the deprecated String.prototype.contains method
     static bool warnOnceAboutStringContains(JSContext* cx, HandleObject strContains) {
         return warnOnceAbout(cx, strContains, WARN_STRING_CONTAINS_DEPRECATED,
                              JSMSG_DEPRECATED_STRING_CONTAINS);
     }
 
-    // Warn about uses of Proxy.create and Proxy.createFunction
-    static bool warnOnceAboutProxyCreate(JSContext* cx, HandleObject create) {
-        return warnOnceAbout(cx, create, WARN_PROXY_CREATE_DEPRECATED,
-                             JSMSG_DEPRECATED_PROXY_CREATE);
-    }
-
     static bool getOrCreateEval(JSContext* cx, Handle<GlobalObject*> global,
                                 MutableHandleObject eval);
 
     // Infallibly test whether the given value is the eval function for this global.
     bool valueIsEval(Value val);
 
     // Implemented in jsiter.cpp.
     static bool initIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -145,22 +145,22 @@ ObjectGroup::useSingletonForClone(JSFunc
      * initialize method. We capture this, along with similar cases, by looking
      * for short scripts which use both .apply and arguments. For such scripts,
      * whenever creating a new instance of the function we both give that
      * instance a singleton type and clone the underlying script.
      */
 
     uint32_t begin, end;
     if (fun->hasScript()) {
-        if (!fun->nonLazyScript()->usesArgumentsApplyAndThis())
+        if (!fun->nonLazyScript()->isLikelyConstructorWrapper())
             return false;
         begin = fun->nonLazyScript()->sourceStart();
         end = fun->nonLazyScript()->sourceEnd();
     } else {
-        if (!fun->lazyScript()->usesArgumentsApplyAndThis())
+        if (!fun->lazyScript()->isLikelyConstructorWrapper())
             return false;
         begin = fun->lazyScript()->begin();
         end = fun->lazyScript()->end();
     }
 
     return end - begin <= 100;
 }
 
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -26,21 +26,21 @@ namespace js {
  *
  * 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 = 350;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 351;
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
 
-static_assert(JSErr_Limit == 419,
+static_assert(JSErr_Limit == 418,
               "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)
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2332,27 +2332,25 @@ nsXPCComponents_Utils::ReportError(Handl
         scripterr = new nsScriptError();
     }
 
     if (err) {
         // It's a proper JS Error
         nsAutoString fileUni;
         CopyUTF8toUTF16(err->filename, fileUni);
 
-        uint32_t column = err->uctokenptr - err->uclinebuf;
-
-        const char16_t* ucmessage =
-            static_cast<const char16_t*>(err->ucmessage);
-        const char16_t* uclinebuf =
-            static_cast<const char16_t*>(err->uclinebuf);
+        uint32_t column = err->tokenOffset();
+
+        const char16_t* ucmessage = err->ucmessage;
+        const char16_t* linebuf = err->linebuf();
 
         nsresult rv = scripterr->InitWithWindowID(
                 ucmessage ? nsDependentString(ucmessage) : EmptyString(),
                 fileUni,
-                uclinebuf ? nsDependentString(uclinebuf) : EmptyString(),
+                linebuf ? nsDependentString(linebuf, err->linebufLength()) : EmptyString(),
                 err->lineno,
                 column, err->flags, "XPConnect JavaScript", innerWindowID);
         NS_ENSURE_SUCCESS(rv, NS_OK);
 
         console->LogMessage(scripterr);
         return NS_OK;
     }
 
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -1244,26 +1244,25 @@ XPCConvert::JSErrorToXPCException(const 
         if (report && report->ucmessage) {
             bestMessage = static_cast<const char16_t*>(report->ucmessage);
         } else if (message) {
             CopyASCIItoUTF16(message, bestMessage);
         } else {
             bestMessage.AssignLiteral("JavaScript Error");
         }
 
-        const char16_t* uclinebuf =
-            static_cast<const char16_t*>(report->uclinebuf);
+        const char16_t* linebuf = report->linebuf();
 
         data = new nsScriptError();
         data->InitWithWindowID(
             bestMessage,
             NS_ConvertASCIItoUTF16(report->filename),
-            uclinebuf ? nsDependentString(uclinebuf) : EmptyString(),
+            linebuf ? nsDependentString(linebuf, report->linebufLength()) : EmptyString(),
             report->lineno,
-            report->uctokenptr - report->uclinebuf, report->flags,
+            report->tokenOffset(), report->flags,
             NS_LITERAL_CSTRING("XPConnect JavaScript"),
             nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx));
     }
 
     if (data) {
         nsAutoCString formattedMsg;
         data->ToString(formattedMsg);
 
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -184,17 +184,17 @@ xpc::ErrorReport::Init(JSErrorReport* aR
     }
 
     if (!aReport->filename) {
         mFileName.SetIsVoid(true);
     } else {
         mFileName.AssignWithConversion(aReport->filename);
     }
 
-    mSourceLine = static_cast<const char16_t*>(aReport->uclinebuf);
+    mSourceLine.Assign(aReport->linebuf(), aReport->linebufLength());
 
     mLineNumber = aReport->lineno;
     mColumn = aReport->column;
     mFlags = aReport->flags;
     mIsMuted = aReport->isMuted;
 }
 
 static PRLogModuleInfo* gJSDiagnostics;
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -953,16 +953,20 @@ nsComboboxControlFrame::ShowDropDown(boo
   }
 }
 
 void
 nsComboboxControlFrame::SetDropDown(nsIFrame* aDropDownFrame)
 {
   mDropdownFrame = aDropDownFrame;
   mListControlFrame = do_QueryFrame(mDropdownFrame);
+  if (!sFocused && nsContentUtils::IsFocusedContent(GetContent())) {
+    sFocused = this;
+    nsListControlFrame::ComboboxFocusSet();
+  }
 }
 
 nsIFrame*
 nsComboboxControlFrame::GetDropDown()
 {
   return mDropdownFrame;
 }
 
@@ -1382,16 +1386,20 @@ nsComboboxControlFrame::CreateFrameFor(n
   nsFrameList textList(textFrame, textFrame);
   mDisplayFrame->SetInitialChildList(kPrincipalList, textList);
   return mDisplayFrame;
 }
 
 void
 nsComboboxControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
+  if (sFocused == this) {
+    sFocused = nullptr;
+  }
+
   // Revoke any pending RedisplayTextEvent
   mRedisplayTextEvent.Revoke();
 
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
 
   if (mDroppedDown) {
     MOZ_ASSERT(mDropdownFrame, "mDroppedDown without frame");
     nsView* view = mDropdownFrame->GetView();
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/select/focusring-1-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"><head>
+    <meta charset="utf-8">
+    <title>Testcase #1 for bug 1253977</title>
+    <style type="text/css">
+
+* { -moz-appearance:none; }
+:focus {
+  border:2px solid black;
+}
+:-moz-focusring {
+  outline: 2px dashed black;
+}
+
+    </style>
+</head>
+<body>
+
+<select><option>1<option>2</select>
+<input>
+
+<script>
+
+function runTests() {
+  var s = document.querySelector("select");
+  var b = document.querySelector("input");
+  setTimeout(function(){ b.focus(); }, 0);
+  setTimeout(function(){ document.body.offsetHeight; document.documentElement.removeAttribute("class"); }, 0);
+}
+
+window.addEventListener("MozReftestInvalidate", runTests, false);
+
+</script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/select/focusring-1.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"><head>
+    <meta charset="utf-8">
+    <title>Testcase #1 for bug 1253977</title>
+    <style type="text/css">
+
+* { -moz-appearance:none; }
+:focus {
+  border:2px solid black;
+}
+:-moz-focusring {
+  outline: 2px dashed black;
+}
+
+    </style>
+</head>
+<body>
+
+<select><option>1<option>2</select>
+<input>
+
+<script>
+
+function runTests() {
+  var s = document.querySelector("select");
+  var b = document.querySelector("input");
+  setTimeout(function(){ s.focus();                  }, 1);
+  setTimeout(function(){ s.style.display = 'none';   }, 2);
+  setTimeout(function(){ b.focus();                  }, 3);
+  setTimeout(function(){ s.style.display = 'inline'; }, 4);
+  setTimeout(function(){ document.body.offsetHeight; document.documentElement.removeAttribute("class"); }, 0);
+}
+
+window.addEventListener("MozReftestInvalidate", runTests, false);
+
+</script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/select/focusring-2-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html><head>
+    <meta charset="utf-8">
+    <title>Testcase #2 for bug 1253977</title>
+    <style type="text/css">
+
+* { -moz-appearance:none; }
+:focus {
+  border:2px solid black;
+}
+:-moz-focusring {
+  outline: 2px dashed black;
+}
+
+    </style>
+</head>
+<body>
+
+<select><option>1<option>2</select>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/select/focusring-2.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"><head>
+    <meta charset="utf-8">
+    <title>Testcase #2 for bug 1253977</title>
+    <style type="text/css">
+
+* { -moz-appearance:none; }
+:focus {
+  border:2px solid black;
+}
+:-moz-focusring {
+  outline: 2px dashed black;
+}
+
+    </style>
+</head>
+<body>
+
+<select><option>1<option>2</select>
+
+<script>
+
+function runTests(){
+  var s = document.querySelector("select");
+  setTimeout(function(){ s.focus();                  }, 1);
+  setTimeout(function(){ s.style.display = 'none';   }, 2);
+  setTimeout(function(){ s.blur();                   }, 3);
+  setTimeout(function(){ s.style.display = 'inline'; }, 4);
+  setTimeout(function(){ document.body.offsetHeight; document.documentElement.removeAttribute("class"); }, 0);
+}
+
+window.addEventListener("MozReftestInvalidate", runTests, false);
+
+</script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/select/focusring-3-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"><head>
+    <meta charset="utf-8">
+    <title>Testcase #3 for bug 1253977</title>
+    <style type="text/css">
+
+* { -moz-appearance:none; }
+:focus {
+  border:2px solid black;
+}
+:-moz-focusring {
+  outline: 2px dashed black;
+}
+
+    </style>
+</head>
+<body>
+
+<select><option>1<option>2</select>
+
+<script>
+
+function runTests(){
+  var s = document.querySelector("select");
+  s.focus();
+  document.body.offsetHeight;
+  setTimeout(function(){ document.documentElement.removeAttribute("class"); }, 100);
+}
+
+window.focus();
+window.addEventListener("MozReftestInvalidate", runTests, false);
+
+</script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/select/focusring-3.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"><head>
+    <meta charset="utf-8">
+    <title>Testcase #3 for bug 1253977</title>
+    <style type="text/css">
+
+* { -moz-appearance:none; }
+:focus {
+  border:2px solid black;
+}
+:-moz-focusring {
+  outline: 2px dashed black;
+}
+
+    </style>
+</head>
+<body>
+
+<select onfocus="continueTest1()"><option>1<option>2</select>
+
+<script>
+
+function continueTest1(){
+  var s = document.querySelector("select");
+  setTimeout(function(){ s.style.display = 'none';   }, 2);
+  setTimeout(function(){ s.style.display = 'inline'; document.body.offsetHeight; }, 4);
+  setTimeout(function(){ document.documentElement.removeAttribute("class"); }, 100);
+}
+function runTests(){
+  var s = document.querySelector("select");
+  s.focus();
+  setTimeout(function(){ s.style.display = 'none';   }, 2);
+  setTimeout(function(){ s.style.display = 'inline'; }, 4);
+  setTimeout(function(){ document.body.offsetHeight; document.documentElement.removeAttribute("class"); }, 0);
+}
+
+window.focus();
+window.addEventListener("MozReftestInvalidate", runTests, false);
+
+</script>
+
+</body>
+</html>
--- a/layout/reftests/forms/select/reftest.list
+++ b/layout/reftests/forms/select/reftest.list
@@ -1,8 +1,11 @@
 skip-if(B2G||Mulet) == out-of-bounds-selectedindex.html out-of-bounds-selectedindex-ref.html # test for bug 471741 # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) == multiple.html multiple-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 == boguskids.html boguskids-ref.html
 == dynamic-boguskids.html boguskids-ref.html
 == option-children.html option-children-ref.html
 fuzzy(1,4) == padding-button-placement.html padding-button-placement-ref.html
 HTTP(../..) == vertical-centering.html vertical-centering-ref.html
 == 997709-2.html 997709-2-ref.html
+needs-focus == focusring-1.html focusring-1-ref.html
+needs-focus == focusring-2.html focusring-2-ref.html
+needs-focus == focusring-3.html focusring-3-ref.html
--- a/layout/tools/reftest/Makefile.in
+++ b/layout/tools/reftest/Makefile.in
@@ -1,36 +1,32 @@
 # vim: set shiftwidth=8 tabstop=8 autoindent noexpandtab copyindent:
 # 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/.
 
 _DEST_DIR = $(DEPTH)/_tests/reftest
 
 _HARNESS_FILES = \
+  $(srcdir)/b2g_start_script.js \
   $(srcdir)/runreftest.py \
   $(srcdir)/reftestcommandline.py \
+  $(srcdir)/reftest-preferences.js \
   $(srcdir)/remotereftest.py \
   $(srcdir)/runreftestb2g.py \
   $(srcdir)/runreftestmulet.py \
   $(srcdir)/gaia_lock_screen.js \
   $(srcdir)/output.py \
   automation.py \
   $(topsrcdir)/build/mobile/b2gautomation.py \
   $(topsrcdir)/build/mobile/remoteautomation.py \
   $(topsrcdir)/testing/mochitest/server.js \
   $(topsrcdir)/build/pgo/server-locations.txt \
   $(NULL)
 
-_HARNESS_PP_FILES = \
-  b2g_start_script.js \
-  $(NULL)
-_HARNESS_PP_FILES_PATH = $(_DEST_DIR)
-PP_TARGETS += _HARNESS_PP_FILES
-
 include $(topsrcdir)/config/rules.mk
 
 # We're installing to _tests/reftest
 TARGET_DEPTH = ../..
 include $(topsrcdir)/build/automation-build.mk
 
 $(_DEST_DIR):
 	$(NSINSTALL) -D $@
--- a/layout/tools/reftest/b2g_start_script.js
+++ b/layout/tools/reftest/b2g_start_script.js
@@ -1,20 +1,13 @@
 /* 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/. */
 
-function setDefaultPrefs() {
-    // This code sets the preferences for extension-based reftest.
-    var prefs = Cc["@mozilla.org/preferences-service;1"].
-                getService(Ci.nsIPrefService);
-    var branch = prefs.getDefaultBranch("");
-
-#include reftest-preferences.js
-}
+const { utils: Cu, classes: Cc, interfaces: Ci } = Components;
 
 function setPermissions() {
   if (__marionetteParams.length < 2) {
     return;
   }
 
   let serverAddr = __marionetteParams[0];
   let serverPort = __marionetteParams[1];
@@ -22,31 +15,29 @@ function setPermissions() {
               .getService(Ci.nsIPermissionManager);
   let ioService = Cc["@mozilla.org/network/io-service;1"]
                   .getService(Ci.nsIIOService);
   let uri = ioService.newURI("http://" + serverAddr + ":" + serverPort, null, null);
   perms.add(uri, "allowXULXBL", Ci.nsIPermissionManager.ALLOW_ACTION);
 }
 
 var cm = Cc["@mozilla.org/categorymanager;1"]
-           .getService(Components.interfaces.nsICategoryManager);
+           .getService(Ci.nsICategoryManager);
 
 // Disable update timers that cause b2g failures.
 if (cm) {
   cm.deleteCategoryEntry("update-timer", "WebappsUpdateTimer", false);
   cm.deleteCategoryEntry("update-timer", "nsUpdateService", false);
 }
 
 // Load into any existing windows
 var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
             .getService(Ci.nsIWindowMediator);
 var win = wm.getMostRecentWindow('');
 
-// Set preferences and permissions
-setDefaultPrefs();
 setPermissions();
 
 // Loading this into the global namespace causes intermittent failures.
 // See bug 882888 for more details.
 var reftest = {};
 Cu.import("chrome://reftest/content/reftest.jsm", reftest);
 
 // Prevent display off during testing.
--- a/layout/tools/reftest/bootstrap.js
+++ b/layout/tools/reftest/bootstrap.js
@@ -1,73 +1,78 @@
-Components.utils.import("resource://gre/modules/FileUtils.jsm");        
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const { utils: Cu, interfaces: Ci, classes: Cc, manager: Cm } = Components;
+
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 
-function loadIntoWindow(window) {}
-function unloadFromWindow(window) {}
+var WindowListener = {
+  onOpenWindow: function(win) {
+    Services.wm.removeListener(WindowListener);
+
+    win = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+    win.addEventListener("load", function listener() {
+      win.removeEventListener("load", listener, false);
+
+      // Load into any existing windows.
+      let windows = Services.wm.getEnumerator("navigator:browser");
+      while (windows.hasMoreElements()) {
+        win = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
+        break;
+      }
 
-function setDefaultPrefs() {
-    // This code sets the preferences for extension-based reftest.
-    var prefs = Components.classes["@mozilla.org/preferences-service;1"].
-                getService(Components.interfaces.nsIPrefService);
-    var branch = prefs.getDefaultBranch("");
+      Cu.import("chrome://reftest/content/reftest.jsm");
+      win.addEventListener("pageshow", function listener() {
+        win.removeEventListener("pageshow", listener);
+        // Add setTimeout here because windows.innerWidth/Height are not set yet.
+        win.setTimeout(function() {OnRefTestLoad(win);}, 0);
+      });
+    }, false);
+  }
+};
+
+function startup(data, reason) {
+  // b2g is bootstrapped by b2g_start_script.js
+  if (Services.appinfo.widgetToolkit == "gonk") {
+    return;
+  }
 
-#include reftest-preferences.js
+  if (Services.appinfo.OS == "Android") {
+    Cm.addBootstrappedManifestLocation(data.installPath);
+    Services.wm.addListener(WindowListener);
+    return;
+  }
+
+  let ios = Cc["@mozilla.org/network/io-service;1"]
+            .getService(Ci.nsIIOService2);
+  ios.manageOfflineStatus = false;
+  ios.offline = false;
+
+  let wwatch = Cc["@mozilla.org/embedcomp/window-watcher;1"]
+                .getService(Ci.nsIWindowWatcher);
+  let dummy = wwatch.openWindow(null, "about:blank", "dummy",
+                                "chrome,dialog=no,left=800,height=200,width=200,all",null);
+  dummy.onload = function() {
+    dummy.focus();
+    wwatch.openWindow(null, "chrome://reftest/content/reftest.xul", "_blank",
+                      "chrome,dialog=no,all", {});
+  };
 }
 
-var windowListener = {
-    onOpenWindow: function(aWindow) {
-        let domWindow = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowInternal || Components.interfaces.nsIDOMWindow);
-        domWindow.addEventListener("load", function() {
-            domWindow.removeEventListener("load", arguments.callee, false);
-
-            let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
+function shutdown(data, reason) {
+  if (Services.appinfo.widgetToolkit == "gonk") {
+    return;
+  }
 
-            // Load into any existing windows
-            let enumerator = wm.getEnumerator("navigator:browser");
-            while (enumerator.hasMoreElements()) {
-                let win = enumerator.getNext().QueryInterface(Components.interfaces.nsIDOMWindow);
-                setDefaultPrefs();
-                Components.utils.import("chrome://reftest/content/reftest.jsm");
-                win.addEventListener("pageshow", function() {
-                    win.removeEventListener("pageshow", arguments.callee); 
-                    // We add a setTimeout here because windows.innerWidth/Height are not set yet;
-                    win.setTimeout(function () {OnRefTestLoad(win);}, 0);
-                });
-                break;
-            }
-        }, false);
-   },
-   onCloseWindow: function(aWindow){ },
-   onWindowTitleChange: function(){ },
-};
-
-function startup(aData, aReason) {
-    let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
-             getService (Components.interfaces.nsIWindowMediator);
-
-    Components.manager.addBootstrappedManifestLocation(aData.installPath);
-
-    // Load into any new windows
-    wm.addListener(windowListener);
+  if (Services.appinfo.OS == "Android") {
+    Services.wm.removeListener(WindowListener);
+    Cm.removedBootstrappedManifestLocation(data.installPath);
+    OnRefTestUnload();
+    Cu.unload("chrome://reftest/content/reftest.jsm");
+  }
 }
 
-function shutdown(aData, aReason) {
-    // When the application is shutting down we normally don't have to clean up any UI changes
-    if (aReason == APP_SHUTDOWN)
-        return;
 
-    let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
-             getService(Components.interfaces.nsIWindowMediator);
-
-    // Stop watching for new windows
-    wm.removeListener(windowListener);
-
-    // Unload from any existing windows
-    let enumerator = wm.getEnumerator("navigator:browser");
-    while (enumerator.hasMoreElements()) {
-        let win = enumerator.getNext().QueryInterface(Components.interfaces.nsIDOMWindow);
-        unloadFromWindow(win);
-    }
-}
-
-function install(aData, aReason) { }
-function uninstall(aData, aReason) { }
-
+function install(data, reason) {}
+function uninstall(data, reason) {}
--- a/layout/tools/reftest/install.rdf
+++ b/layout/tools/reftest/install.rdf
@@ -1,19 +1,17 @@
 <?xml version="1.0"?>
 
 <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns:em="http://www.mozilla.org/2004/em-rdf#">
   <Description about="urn:mozilla:install-manifest">
     <em:id>reftest@mozilla.org</em:id>
-#ifdef BOOTSTRAP
+    <em:version>1.0</em:version>
     <em:type>2</em:type>
     <em:bootstrap>true</em:bootstrap>
-#endif
-    <em:version>1.0</em:version>
     <em:targetApplication>
       <Description>
         <em:id>toolkit@mozilla.org</em:id>
 #expand        <em:minVersion>__MOZILLA_VERSION_U__</em:minVersion>
 #expand        <em:maxVersion>__MOZILLA_VERSION_U__</em:maxVersion>
       </Description>
     </em:targetApplication>
     <!-- Front End MetaData -->
--- a/layout/tools/reftest/jar.mn
+++ b/layout/tools/reftest/jar.mn
@@ -1,11 +1,7 @@
 reftest.jar:
 % content reftest %content/
 *  content/reftest-content.js (reftest-content.js)
   content/httpd.jsm (../../../netwerk/test/httpserver/httpd.js)
   content/StructuredLog.jsm (../../../testing/modules/StructuredLog.jsm)
-#ifdef BOOTSTRAP
-*  content/reftest.jsm (reftest.js)
-#else
-*  content/reftest.js (reftest.js)
+*  content/reftest.jsm (reftest.jsm)
   content/reftest.xul (reftest.xul)
-#endif
--- a/layout/tools/reftest/moz.build
+++ b/layout/tools/reftest/moz.build
@@ -2,30 +2,13 @@
 # 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/.
 
 with Files('**'):
     BUG_COMPONENT = ('Testing', 'Reftest')
 
-if CONFIG['MOZ_BUILD_APP'] in ('b2g', 'b2g/dev', 'mobile/android'):
-    DEFINES['BOOTSTRAP'] = True
-    if CONFIG['MOZ_BUILD_APP'] in ('b2g', 'b2g/dev'):
-        DEFINES['REFTEST_B2G'] = True
-else:
-    EXTRA_PP_COMPONENTS += [
-        'reftest-cmdline.js',
-    ]
-    EXTRA_COMPONENTS += [
-        'reftest-cmdline.manifest',
-    ]
-
+XPI_NAME = 'reftest'
+USE_EXTENSION_MANIFEST = True
 JAR_MANIFESTS += ['jar.mn']
-
-USE_EXTENSION_MANIFEST = True
-
-XPI_NAME = 'reftest'
-
 FINAL_TARGET_PP_FILES += ['install.rdf']
-
-if CONFIG['MOZ_BUILD_APP'] == 'mobile/android':
-    FINAL_TARGET_PP_FILES += ['bootstrap.js']
+FINAL_TARGET_FILES += ['bootstrap.js']
deleted file mode 100644
--- a/layout/tools/reftest/reftest-cmdline.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/* 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/. */
-
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-const nsISupports                    = Components.interfaces.nsISupports;
-  
-const nsICommandLine                 = Components.interfaces.nsICommandLine;
-const nsICommandLineHandler          = Components.interfaces.nsICommandLineHandler;
-const nsISupportsString              = Components.interfaces.nsISupportsString;
-const nsIWindowWatcher               = Components.interfaces.nsIWindowWatcher;
-
-function RefTestCmdLineHandler() {}
-RefTestCmdLineHandler.prototype =
-{
-  classID: Components.ID('{32530271-8c1b-4b7d-a812-218e42c6bb23}'),
-
-  /* nsISupports */
-  QueryInterface: XPCOMUtils.generateQI([nsICommandLineHandler]),
-
-  /* nsICommandLineHandler */
-  handle : function handler_handle(cmdLine) {
-    /* Ignore the platform's online/offline status while running reftests. */
-    var ios = Components.classes["@mozilla.org/network/io-service;1"]
-              .getService(Components.interfaces.nsIIOService2);
-    ios.manageOfflineStatus = false;
-    ios.offline = false;
-
-    /**
-     * Manipulate preferences by adding to the *default* branch.  Adding
-     * to the default branch means the changes we make won't get written
-     * back to user preferences.
-     *
-     * We want to do this here rather than in reftest.js because it's
-     * important to force sRGB as an output profile for color management
-     * before we load a window.
-     */
-    var prefs = Components.classes["@mozilla.org/preferences-service;1"].
-                getService(Components.interfaces.nsIPrefService);
-    var branch = prefs.getDefaultBranch("");
-
-#include reftest-preferences.js
-
-    var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-                           .getService(nsIWindowWatcher);
-
-    function loadReftests() {
-      wwatch.openWindow(null, "chrome://reftest/content/reftest.xul", "_blank",
-                        "chrome,dialog=no,all", {});
-    }
-
-    var remote = false;
-    try {
-      remote = prefs.getBoolPref("reftest.remote");
-    } catch (ex) {
-    }
-
-    // If we are running on a remote machine, assume that we can't open another
-    // window for transferring focus to when tests don't require focus.
-    if (remote) {
-      loadReftests();
-    }
-    else {
-      // This dummy window exists solely for enforcing proper focus discipline.
-      var dummy = wwatch.openWindow(null, "about:blank", "dummy",
-                                    "chrome,dialog=no,left=800,height=200,width=200,all", null);
-      dummy.onload = function dummyOnload() {
-        dummy.focus();
-        loadReftests();
-      }
-    }
-
-    cmdLine.preventDefault = true;
-  },
-
-  helpInfo : "  --reftest <file>   Run layout acceptance tests on given manifest.\n"
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RefTestCmdLineHandler]);
deleted file mode 100644
--- a/layout/tools/reftest/reftest-cmdline.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-component {32530271-8c1b-4b7d-a812-218e42c6bb23} reftest-cmdline.js
-contract @mozilla.org/commandlinehandler/general-startup;1?type=reftest {32530271-8c1b-4b7d-a812-218e42c6bb23}
-category command-line-handler m-reftest @mozilla.org/commandlinehandler/general-startup;1?type=reftest
--- a/layout/tools/reftest/reftest-preferences.js
+++ b/layout/tools/reftest/reftest-preferences.js
@@ -1,70 +1,112 @@
-    // For mochitests, we're more interested in testing the behavior of in-
-    // content XBL bindings, so we set this pref to true. In reftests, we're
-    // more interested in testing the behavior of XBL as it works in chrome,
-    // so we want this pref to be false.
-    branch.setBoolPref("dom.use_xbl_scopes_for_remote_xul", false);
-    branch.setIntPref("gfx.color_management.mode", 2);
-    branch.setBoolPref("gfx.color_management.force_srgb", true);
-    branch.setBoolPref("browser.dom.window.dump.enabled", true);
-    branch.setIntPref("ui.caretBlinkTime", -1);
-    branch.setBoolPref("dom.send_after_paint_to_content", true);
-    // no slow script dialogs
-    branch.setIntPref("dom.max_script_run_time", 0);
-    branch.setIntPref("dom.max_chrome_script_run_time", 0);
-    branch.setIntPref("hangmonitor.timeout", 0);
-    // Ensure autoplay is enabled for all platforms.
-    branch.setBoolPref("media.autoplay.enabled", true);
-    // Disable updates
-    branch.setBoolPref("app.update.enabled", false);
-    // Disable addon updates and prefetching so we don't leak them
-    branch.setBoolPref("extensions.update.enabled", false);
-    branch.setBoolPref("extensions.getAddons.cache.enabled", false);
-    // Disable blocklist updates so we don't have them reported as leaks
-    branch.setBoolPref("extensions.blocklist.enabled", false);
-    // Make url-classifier updates so rare that they won't affect tests
-    branch.setIntPref("urlclassifier.updateinterval", 172800);
-    // Disable downscale-during-decode, since it makes reftests more difficult.
-    branch.setBoolPref("image.downscale-during-decode.enabled", false);
-    // Disable the single-color optimization, since it can cause intermittent
-    // oranges and it causes many of our tests to test a different code path
-    // than the one that normal images on the web use.
-    branch.setBoolPref("image.single-color-optimization.enabled", false);
-    // Checking whether two files are the same is slow on Windows.
-    // Setting this pref makes tests run much faster there.
-    branch.setBoolPref("security.fileuri.strict_origin_policy", false);
-    // Disable the thumbnailing service
-    branch.setBoolPref("browser.pagethumbnails.capturing_disabled", true);
-    // Since our tests are 800px wide, set the assume-designed-for width of all
-    // pages to be 800px (instead of the default of 980px). This ensures that
-    // in our 800px window we don't zoom out by default to try to fit the
-    // assumed 980px content.
-    branch.setIntPref("browser.viewport.desktopWidth", 800);
-    // Disable the fade out (over time) of overlay scrollbars, since we
-    // can't guarantee taking both reftest snapshots at the same point
-    // during the fade.
-    branch.setBoolPref("layout.testing.overlay-scrollbars.always-visible", true);
-    // Disable interruptible reflow since (1) it's normally not going to
-    // happen, but (2) it might happen if we somehow end up with both
-    // pending user events and clock skew.  So to avoid having to change
-    // MakeProgress to deal with waiting for interruptible reflows to
-    // complete for a rare edge case, we just disable interruptible
-    // reflow so that that rare edge case doesn't lead to reftest
-    // failures.
-    branch.setBoolPref("layout.interruptible-reflow.enabled", false);
+// For mochitests, we're more interested in testing the behavior of in-
+// content XBL bindings, so we set this pref to true. In reftests, we're
+// more interested in testing the behavior of XBL as it works in chrome,
+// so we want this pref to be false.
+user_pref("dom.use_xbl_scopes_for_remote_xul", false);
+user_pref("gfx.color_management.mode", 2);
+user_pref("gfx.color_management.force_srgb", true);
+user_pref("browser.dom.window.dump.enabled", true);
+user_pref("ui.caretBlinkTime", -1);
+user_pref("dom.send_after_paint_to_content", true);
+// no slow script dialogs
+user_pref("dom.max_script_run_time", 0);
+user_pref("dom.max_chrome_script_run_time", 0);
+user_pref("hangmonitor.timeout", 0);
+// Ensure autoplay is enabled for all platforms.
+user_pref("media.autoplay.enabled", true);
+// Disable updates
+user_pref("app.update.enabled", false);
+user_pref("app.update.staging.enabled", false);
+user_pref("app.update.url.android", "");
+// Disable addon updates and prefetching so we don't leak them
+user_pref("extensions.update.enabled", false);
+user_pref("extensions.systemAddon.update.url", "http://localhost/dummy-system-addons.xml");
+user_pref("extensions.getAddons.cache.enabled", false);
+// Disable blocklist updates so we don't have them reported as leaks
+user_pref("extensions.blocklist.enabled", false);
+// Make url-classifier updates so rare that they won't affect tests
+user_pref("urlclassifier.updateinterval", 172800);
+// Disable downscale-during-decode, since it makes reftests more difficult.
+user_pref("image.downscale-during-decode.enabled", false);
+// Disable the single-color optimization, since it can cause intermittent
+// oranges and it causes many of our tests to test a different code path
+// than the one that normal images on the web use.
+user_pref("image.single-color-optimization.enabled", false);
+// Checking whether two files are the same is slow on Windows.
+// Setting this pref makes tests run much faster there.
+user_pref("security.fileuri.strict_origin_policy", false);
+// Disable the thumbnailing service
+user_pref("browser.pagethumbnails.capturing_disabled", true);
+// Since our tests are 800px wide, set the assume-designed-for width of all
+// pages to be 800px (instead of the default of 980px). This ensures that
+// in our 800px window we don't zoom out by default to try to fit the
+// assumed 980px content.
+user_pref("browser.viewport.desktopWidth", 800);
+// Disable the fade out (over time) of overlay scrollbars, since we
+// can't guarantee taking both reftest snapshots at the same point
+// during the fade.
+user_pref("layout.testing.overlay-scrollbars.always-visible", true);
+// Disable interruptible reflow since (1) it's normally not going to
+// happen, but (2) it might happen if we somehow end up with both
+// pending user events and clock skew.  So to avoid having to change
+// MakeProgress to deal with waiting for interruptible reflows to
+// complete for a rare edge case, we just disable interruptible
+// reflow so that that rare edge case doesn't lead to reftest
+// failures.
+user_pref("layout.interruptible-reflow.enabled", false);
 
-    // Tell the search service we are running in the US.  This also has the
-    // desired side-effect of preventing our geoip lookup.
-    branch.setBoolPref("browser.search.isUS", true);
-    branch.setCharPref("browser.search.countryCode", "US");
-    // Prevent the geoSpecificDefaults XHR by emptying the URL.
-    branch.setCharPref("browser.search.geoSpecificDefaults.url", "");
+// Tell the search service we are running in the US.  This also has the
+// desired side-effect of preventing our geoip lookup.
+user_pref("browser.search.isUS", true);
+user_pref("browser.search.countryCode", "US");
+user_pref("browser.search.geoSpecificDefaults", false);
+
+// Make sure SelfSupport doesn't hit the network.
+user_pref("browser.selfsupport.url", "https://localhost/selfsupport-dummy/");
+
+// use about:blank, not browser.startup.homepage
+user_pref("browser.startup.page", 0);
+
+// Allow XUL and XBL files to be opened from file:// URIs
+user_pref("dom.allow_XUL_XBL_for_file", true);
+
+// Allow view-source URIs to be opened from URIs that share
+// their protocol with the inner URI of the view-source URI
+user_pref("security.view-source.reachable-from-inner-protocol", true);
 
-    // Make sure SelfSupport doesn't hit the network.
-    branch.setCharPref("browser.selfsupport.url", "https://%(server)s/selfsupport-dummy/");
+// Ensure that telemetry is disabled, so we don't connect to the telemetry
+// server in the middle of the tests.
+user_pref("toolkit.telemetry.enabled", false);
+user_pref("toolkit.telemetry.unified", false);
+// Likewise for safebrowsing.
+user_pref("browser.safebrowsing.enabled", false);
+user_pref("browser.safebrowsing.malware.enabled", false);
+// Likewise for tracking protection.
+user_pref("privacy.trackingprotection.enabled", false);
+user_pref("privacy.trackingprotection.pbmode.enabled", false);
+// And for snippets.
+user_pref("browser.snippets.enabled", false);
+user_pref("browser.snippets.syncPromo.enabled", false);
+user_pref("browser.snippets.firstrunHomepage.enabled", false);
+// And for useragent updates.
+user_pref("general.useragent.updates.enabled", false);
+// And for webapp updates.  Yes, it is supposed to be an integer.
+user_pref("browser.webapps.checkForUpdates", 0);
+// And for about:newtab content fetch and pings.
+user_pref("browser.newtabpage.directory.source", "data:application/json,{\"reftest\":1}");
+user_pref("browser.newtabpage.directory.ping", "");
+// Only allow add-ons from the profile and app and allow foreign
+// injection
+user_pref("extensions.enabledScopes", 5);
+user_pref("extensions.autoDisableScopes", 0);
+// Allow unsigned add-ons
+user_pref("xpinstall.signatures.required", false);
 
-    // Allow XUL and XBL files to be opened from file:// URIs
-    branch.setBoolPref("dom.allow_XUL_XBL_for_file", true);
+// Don't use auto-enabled e10s
+user_pref("browser.tabs.remote.autostart.1", false);
+user_pref("browser.tabs.remote.autostart.2", false);
 
-    // Allow view-source URIs to be opened from URIs that share
-    // their protocol with the inner URI of the view-source URI
-    branch.setBoolPref("security.view-source.reachable-from-inner-protocol", true);
+user_pref("startup.homepage_welcome_url", "");
+user_pref("startup.homepage_override_url", "");
+
+user_pref("media.gmp-manager.url.override", "http://localhost/dummy-gmp-manager.xml");
rename from layout/tools/reftest/reftest.js
rename to layout/tools/reftest/reftest.jsm
--- a/layout/tools/reftest/reftest.js
+++ b/layout/tools/reftest/reftest.jsm
@@ -1,18 +1,15 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- /
 /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#if BOOTSTRAP
-this.EXPORTED_SYMBOLS = ["OnRefTestLoad"];
-#endif
-
+this.EXPORTED_SYMBOLS = ["OnRefTestLoad", "OnRefTestUnload"];
 
 var CC = Components.classes;
 const CI = Components.interfaces;
 const CR = Components.results;
 const CU = Components.utils;
 
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@@ -175,39 +172,43 @@ function HasUnexpectedResult()
            gTestResults.FailedLoad > 0 ||
            gTestResults.UnexpectedFail > 0 ||
            gTestResults.UnexpectedPass > 0 ||
            gTestResults.AssertionUnexpected > 0 ||
            gTestResults.AssertionUnexpectedFixed > 0;
 }
 
 // By default we just log to stdout
-var gDumpFn = dump;
+var gLogFile = null;
 var gDumpRawLog = function(record) {
   // Dump JSON representation of data on a single line
-  var line = JSON.stringify(record);
-  gDumpFn("\n" + line + "\n");
+  var line = "\n" + JSON.stringify(record) + "\n";
+  dump(line);
+
+  if (gLogFile) {
+    gLogFile.write(line, line.length);
+  }
 }
 var logger = new StructuredLogger('reftest', gDumpRawLog);
 
 function TestBuffer(str)
 {
-    logger.debug(str);
-    gTestLog.push(str);
+  logger.debug(str);
+  gTestLog.push(str);
 }
 
 function FlushTestBuffer()
 {
-    // In debug mode, we've dumped all these messages already.
-    if (gLogLevel !== 'debug') {
-        for (var i = 0; i < gTestLog.length; ++i) {
-            logger.info("Saved log: " + gTestLog[i]);
-        }
+  // In debug mode, we've dumped all these messages already.
+  if (gLogLevel !== 'debug') {
+    for (var i = 0; i < gTestLog.length; ++i) {
+      logger.info("Saved log: " + gTestLog[i]);
     }
-    gTestLog = [];
+  }
+  gTestLog = [];
 }
 
 function AllocateCanvas()
 {
     if (gRecycledCanvases.length > 0)
         return gRecycledCanvases.shift();
 
     var canvas = gContainingWindow.document.createElementNS(XHTML_NS, "canvas");
@@ -300,29 +301,30 @@ this.OnRefTestLoad = function OnRefTestL
     }
     gBrowser.setAttribute("id", "browser");
     gBrowser.setAttribute("type", "content-primary");
     gBrowser.setAttribute("remote", gBrowserIsRemote ? "true" : "false");
     // Make sure the browser element is exactly 800x1000, no matter
     // what size our window is
     gBrowser.setAttribute("style", "padding: 0px; margin: 0px; border:none; min-width: 800px; min-height: 1000px; max-width: 800px; max-height: 1000px");
 
-#ifdef BOOTSTRAP
-#ifdef REFTEST_B2G
-    var doc = gContainingWindow.document.getElementsByTagName("html")[0];
-#else
-    var doc = gContainingWindow.document.getElementById('main-window');
-#endif
-    while (doc.hasChildNodes()) {
-      doc.removeChild(doc.firstChild);
+    if (Services.appinfo.OS == "Android") {
+      let doc;
+      if (Services.appinfo.widgetToolkit == "gonk") {
+        doc = gContainingWindow.document.getElementsByTagName("html")[0];
+      } else {
+        doc = gContainingWindow.document.getElementById('main-window');
+      }
+      while (doc.hasChildNodes()) {
+        doc.removeChild(doc.firstChild);
+      }
+      doc.appendChild(gBrowser);
+    } else {
+      document.getElementById("reftest-window").appendChild(gBrowser);
     }
-    doc.appendChild(gBrowser);
-#else
-    document.getElementById("reftest-window").appendChild(gBrowser);
-#endif
 
     // reftests should have the test plugins enabled, not click-to-play
     let plugin1 = getTestPlugin("Test Plug-in");
     let plugin2 = getTestPlugin("Second Test Plug-in");
     if (plugin1 && plugin2) {
       gTestPluginEnabledStates = [plugin1.enabledState, plugin2.enabledState];
       plugin1.enabledState = CI.nsIPluginTag.STATE_ENABLED;
       plugin2.enabledState = CI.nsIPluginTag.STATE_ENABLED;
@@ -357,37 +359,18 @@ function InitAndStartRefTests()
     } catch(e) {
         gLoadTimeout = 5 * 60 * 1000; //5 minutes as per bug 479518
     }
 
     /* Get the logfile for android tests */
     try {
         var logFile = prefs.getCharPref("reftest.logFile");
         if (logFile) {
-            try {
-                var f = FileUtils.File(logFile);
-                var mfl = FileUtils.openFileOutputStream(f, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE);
-                // Set to mirror to stdout as well as the file
-                gDumpFn = function (msg) {
-#ifdef BOOTSTRAP
-#ifdef REFTEST_B2G
-                    dump(msg);
-#else
-                    //NOTE: on android-xul, we have a libc crash if we do a dump with %7s in the string
-#endif
-#else
-                    dump(msg);
-#endif
-                    mfl.write(msg, msg.length);
-                };
-            }
-            catch(e) {
-                // If there is a problem, just use stdout
-                gDumpFn = dump;
-            }
+            var f = FileUtils.File(logFile);
+            gLogFile = FileUtils.openFileOutputStream(f, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE);
         }
     } catch(e) {}
 
     try {
         gRemote = prefs.getBoolPref("reftest.remote");
     } catch(e) {
         gRemote = false;
     }
@@ -1377,18 +1360,18 @@ function StartCurrentURI(aState)
         gURLs[0].maxAsserts == 0) {
         // Pretend the document loaded --- RecordResult will notice
         // there's already a canvas for this URL
         gContainingWindow.setTimeout(RecordResult, 0);
     } else {
         var currentTest = gTotalTests - gURLs.length;
         // Log this to preserve the same overall log format,
         // should be removed if the format is updated
-        gDumpFn("REFTEST TEST-LOAD | " + gCurrentURL + " | " + currentTest + " / " + gTotalTests +
-                " (" + Math.floor(100 * (currentTest / gTotalTests)) + "%)\n");
+        dump("REFTEST TEST-LOAD | " + gCurrentURL + " | " + currentTest + " / " + gTotalTests +
+             " (" + Math.floor(100 * (currentTest / gTotalTests)) + "%)\n");
         TestBuffer("START " + gCurrentURL);
         var type = gURLs[0].type
         if (TYPE_SCRIPT == type) {
             SendLoadScriptTest(gCurrentURL, gLoadTimeout);
         } else {
             SendLoadTest(type, gCurrentURL, gLoadTimeout);
         }
     }
@@ -1830,29 +1813,29 @@ function DoAssertionCheck(numAsserts)
         var expectedAssertions = "expected " + minAsserts;
         if (minAsserts != maxAsserts) {
             expectedAssertions += " to " + maxAsserts;
         }
         expectedAssertions += " assertions";
 
         if (numAsserts < minAsserts) {
             ++gTestResults.AssertionUnexpectedFixed;
-            gDumpFn("REFTEST TEST-UNEXPECTED-PASS | " + gURLs[0].prettyPath +
-                    " | assertion count" + numAsserts + " is less than " +
+            dump("REFTEST TEST-UNEXPECTED-PASS | " + gURLs[0].prettyPath +
+                 " | assertion count" + numAsserts + " is less than " +
                     expectedAssertions + "\n");
         } else if (numAsserts > maxAsserts) {
             ++gTestResults.AssertionUnexpected;
-            gDumpFn("REFTEST TEST-UNEXPECTED-FAIL | " + gURLs[0].prettyPath +
-                    " | assertion count " + numAsserts + " is more than " +
+            dump("REFTEST TEST-UNEXPECTED-FAIL | " + gURLs[0].prettyPath +
+                 " | assertion count " + numAsserts + " is more than " +
                     expectedAssertions + "\n");
         } else if (numAsserts != 0) {
             ++gTestResults.AssertionKnown;
-            gDumpFn("REFTEST TEST-KNOWN-FAIL | " + gURLs[0].prettyPath +
-                    "assertion count " + numAsserts + " matches " +
-                    expectedAssertions + "\n");
+            dump("REFTEST TEST-KNOWN-FAIL | " + gURLs[0].prettyPath +
+                 "assertion count " + numAsserts + " matches " +
+                 expectedAssertions + "\n");
         }
     }
 
     if (gURLs[0].chaosMode) {
         gWindowUtils.leaveChaosMode();
     }
 
     // And start the next test.
--- a/layout/tools/reftest/reftest.xul
+++ b/layout/tools/reftest/reftest.xul
@@ -4,11 +4,11 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         id="reftest-window"
         hidechrome="true"
         onload="OnRefTestLoad();"
         onunload="OnRefTestUnload();"
         style="background:white; overflow:hidden"
         >
-    <script type="application/ecmascript" src="reftest.js" />
+    <script type="application/ecmascript" src="reftest.jsm" />
     <!-- The reftest browser element is dynamically created, here -->
 </window>
--- a/layout/tools/reftest/reftestcommandline.py
+++ b/layout/tools/reftest/reftestcommandline.py
@@ -125,16 +125,20 @@ class ReftestArgumentsParser(argparse.Ar
                           action="append",
                           dest="extensionsToInstall",
                           default=[],
                           help="install the specified extension in the testing profile. "
                           "The extension file's name should be <id>.xpi where <id> is "
                           "the extension's id as indicated in its install.rdf. "
                           "An optional path can be specified too.")
 
+        self.add_argument("--marionette",
+                          default=None,
+                          help="host:port to use when connecting to Marionette")
+
         self.add_argument("--setenv",
                           action="append",
                           type=str,
                           default=[],
                           dest="environment",
                           metavar="NAME=VALUE",
                           help="sets the given variable in the application's "
                           "environment")
@@ -383,22 +387,16 @@ class B2GArgumentParser(ReftestArguments
                           help="Optional command-line arg to pass to the browser")
 
         self.add_argument("--b2gpath",
                           action="store",
                           type=str,
                           dest="b2gPath",
                           help="path to B2G repo or qemu dir")
 
-        self.add_argument("--marionette",
-                          action="store",
-                          type=str,
-                          dest="marionette",
-                          help="host:port to use when connecting to Marionette")
-
         self.add_argument("--emulator",
                           action="store",
                           type=str,
                           dest="emulator",
                           help="Architecture of emulator to use: x86 or arm")
 
         self.add_argument("--emulator-res",
                           action="store",
@@ -651,22 +649,16 @@ class RemoteArgumentsParser(ReftestArgum
 
         self.add_argument("--pidfile",
                           action="store",
                           type=str,
                           dest="pidFile",
                           default="",
                           help="name of the pidfile to generate")
 
-        self.add_argument("--bootstrap",
-                          action="store_true",
-                          dest="bootstrap",
-                          default=False,
-                          help="test with a bootstrap addon required for native Fennec")
-
         self.add_argument("--dm_trans",
                           action="store",
                           type=str,
                           dest="dm_trans",
                           default="sut",
                           help="the transport to use to communicate with device: [adb|sut]; default=sut")
 
         self.add_argument("--remoteTestRoot",
--- a/layout/tools/reftest/remotereftest.py
+++ b/layout/tools/reftest/remotereftest.py
@@ -121,16 +121,17 @@ class ReftestServer:
 
                 rtncode = self._process.poll()
                 if (rtncode == None):
                     self._process.terminate()
             except:
                 self._process.kill()
 
 class RemoteReftest(RefTest):
+    use_marionette = False
     remoteApp = ''
     resolver_cls = RemoteReftestResolver
 
     def __init__(self, automation, devicemanager, options, scriptDir):
         RefTest.__init__(self)
         self.automation = automation
         self._devicemanager = devicemanager
         self.scriptDir = scriptDir
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -28,16 +28,22 @@ import mozinfo
 import mozleak
 import mozlog
 import mozprocess
 import mozprofile
 import mozrunner
 from mozrunner.utils import get_stack_fixer_function, test_environment
 from mozscreenshot import printstatus, dump_screen
 
+try:
+    from marionette import Marionette
+    from marionette_driver.addons import Addons
+except ImportError:
+    Marionette=None
+
 from output import OutputHandler, ReftestFormatter
 import reftestcommandline
 
 here = os.path.abspath(os.path.dirname(__file__))
 
 try:
     from mozbuild.base import MozbuildObject
     build_obj = MozbuildObject.from_environment(cwd=here)
@@ -60,29 +66,29 @@ summaryLines = [('Successful', [('pass',
                                     ('skipped', 'skipped'),
                                     ('slow', 'slow')])]
 
 # Python's print is not threadsafe.
 printLock = threading.Lock()
 
 
 class ReftestThread(threading.Thread):
-    def __init__(self, cmdlineArgs):
+    def __init__(self, cmdargs):
         threading.Thread.__init__(self)
-        self.cmdlineArgs = cmdlineArgs
+        self.cmdargs = cmdargs
         self.summaryMatches = {}
         self.retcode = -1
         for text, _ in summaryLines:
             self.summaryMatches[text] = None
 
     def run(self):
         with printLock:
-            print "Starting thread with", self.cmdlineArgs
+            print "Starting thread with", self.cmdargs
             sys.stdout.flush()
-        process = subprocess.Popen(self.cmdlineArgs, stdout=subprocess.PIPE)
+        process = subprocess.Popen(self.cmdargs, stdout=subprocess.PIPE)
         for chunk in self.chunkForMergedOutput(process.stdout):
             with printLock:
                 print chunk,
                 sys.stdout.flush()
         self.retcode = process.wait()
 
     def chunkForMergedOutput(self, logsource):
         """Gather lines together that should be printed as one atomic unit.
@@ -186,17 +192,19 @@ class ReftestResolver(object):
 
         for key in manifests.iterkeys():
             if None in manifests[key]:
                 manifests[key] = None
             else:
                 manifests[key] = "|".join(list(manifests[key]))
         return manifests
 
+
 class RefTest(object):
+    use_marionette = True
     oldcwd = os.getcwd()
     resolver_cls = ReftestResolver
 
     def __init__(self):
         self.update_mozinfo()
         self.lastTestSeen = 'reftest'
         self.haveDumpedScreen = False
         self.resolver = self.resolver_cls()
@@ -236,25 +244,26 @@ class RefTest(object):
     def createReftestProfile(self, options, manifests, server='localhost', port=0,
                              profile_to_clone=None):
         """Sets up a profile for reftest.
 
         :param options: Object containing command line options
         :param manifests: Dictionary of the form {manifest_path: [filters]}
         :param server: Server name to use for http tests
         :param profile_to_clone: Path to a profile to use as the basis for the
-                                 test profile"""
+                                 test profile
+        """
 
         locations = mozprofile.permissions.ServerLocations()
         locations.add_host(server, scheme='http', port=port)
         locations.add_host(server, scheme='https', port=port)
 
         # Set preferences for communication between our command line arguments
         # and the reftest harness.  Preferences that are required for reftest
-        # to work should instead be set in reftest-cmdline.js .
+        # to work should instead be set in reftest-preferences.js .
         prefs = {}
         prefs['reftest.timeout'] = options.timeout * 1000
         if options.totalChunks:
             prefs['reftest.totalChunks'] = options.totalChunks
         if options.thisChunk:
             prefs['reftest.thisChunk'] = options.thisChunk
         if options.logFile:
             prefs['reftest.logFile'] = options.logFile
@@ -265,68 +274,48 @@ class RefTest(object):
         if options.repeat:
             prefs['reftest.repeat'] = options.repeat
         if options.runUntilFailure:
             prefs['reftest.runUntilFailure'] = True
         prefs['reftest.focusFilterMode'] = options.focusFilterMode
         prefs['reftest.logLevel'] = options.log_tbpl_level or 'info'
         prefs['reftest.manifests'] = json.dumps(manifests)
 
-        # Ensure that telemetry is disabled, so we don't connect to the telemetry
-        # server in the middle of the tests.
-        prefs['toolkit.telemetry.enabled'] = False
-        prefs['toolkit.telemetry.unified'] = False
-        # Likewise for safebrowsing.
-        prefs['browser.safebrowsing.enabled'] = False
-        prefs['browser.safebrowsing.malware.enabled'] = False
-        # Likewise for tracking protection.
-        prefs['privacy.trackingprotection.enabled'] = False
-        prefs['privacy.trackingprotection.pbmode.enabled'] = False
-        # And for snippets.
-        prefs['browser.snippets.enabled'] = False
-        prefs['browser.snippets.syncPromo.enabled'] = False
-        prefs['browser.snippets.firstrunHomepage.enabled'] = False
-        # And for useragent updates.
-        prefs['general.useragent.updates.enabled'] = False
-        # And for webapp updates.  Yes, it is supposed to be an integer.
-        prefs['browser.webapps.checkForUpdates'] = 0
-        # And for about:newtab content fetch and pings.
-        prefs['browser.newtabpage.directory.source'] = 'data:application/json,{"reftest":1}'
-        prefs['browser.newtabpage.directory.ping'] = ''
-        # Only allow add-ons from the profile and app and allow foreign
-        # injection
-        prefs["extensions.enabledScopes"] = 5
-        prefs["extensions.autoDisableScopes"] = 0
-        # Allow unsigned add-ons
-        prefs['xpinstall.signatures.required'] = False
-
-        # Don't use auto-enabled e10s
-        prefs['browser.tabs.remote.autostart.1'] = False
-        prefs['browser.tabs.remote.autostart.2'] = False
         if options.e10s:
             prefs['browser.tabs.remote.autostart'] = True
             prefs['extensions.e10sBlocksEnabling'] = False
 
+        if options.marionette:
+            port = options.marionette.split(':')[1]
+            prefs['marionette.defaultPrefs.port'] = int(port)
+
+        preference_file = os.path.join(here, 'reftest-preferences.js')
+        prefs.update(mozprofile.Preferences.read_prefs(preference_file))
+
         for v in options.extraPrefs:
             thispref = v.split('=')
             if len(thispref) < 2:
                 print "Error: syntax error in --setpref=" + v
                 sys.exit(1)
-            prefs[thispref[0]] = mozprofile.Preferences.cast(
-                thispref[1].strip())
+            prefs[thispref[0]] = thispref[1].strip()
 
-        # install the reftest extension bits into the profile
-        addons = [options.reftestExtensionPath]
+        addons = []
+        if not self.use_marionette:
+            addons.append(options.reftestExtensionPath)
 
         if options.specialPowersExtensionPath is not None:
-            addons.append(options.specialPowersExtensionPath)
+            if not self.use_marionette:
+                addons.append(options.specialPowersExtensionPath)
             # SpecialPowers requires insecure automation-only features that we
             # put behind a pref.
             prefs['security.turn_off_all_security_so_that_viruses_can_take_over_this_computer'] = True
 
+        for pref in prefs:
+            prefs[pref] = mozprofile.Preferences.cast(prefs[pref])
+
         # Install distributed extensions, if application has any.
         distExtDir = os.path.join(options.app[:options.app.rfind(os.sep)],
                                   "distribution", "extensions")
         if os.path.isdir(distExtDir):
             for f in os.listdir(distExtDir):
                 addons.append(os.path.join(distExtDir, f))
 
         # Install custom extensions.
@@ -400,33 +389,34 @@ class RefTest(object):
                                             processOutputLine=_psKill)
         process.run()
         process.wait()
 
     def cleanup(self, profileDir):
         if profileDir:
             shutil.rmtree(profileDir, True)
 
-    def runTests(self, tests, options, cmdlineArgs=None):
+    def runTests(self, tests, options, cmdargs=None):
+        cmdargs = cmdargs or []
         self._populate_logger(options)
 
         # Despite our efforts to clean up servers started by this script, in practice
         # we still see infrequent cases where a process is orphaned and interferes
         # with future tests, typically because the old server is keeping the port in use.
         # Try to avoid those failures by checking for and killing orphan servers before
         # trying to start new ones.
         self.killNamedOrphans('ssltunnel')
         self.killNamedOrphans('xpcshell')
 
         manifests = self.resolver.resolveManifests(options, tests)
         if options.filter:
             manifests[""] = options.filter
 
-        if not hasattr(options, "runTestsInParallel") or not options.runTestsInParallel:
-            return self.runSerialTests(manifests, options, cmdlineArgs)
+        if not getattr(options, 'runTestsInParallel', False):
+            return self.runSerialTests(manifests, options, cmdargs)
 
         cpuCount = multiprocessing.cpu_count()
 
         # We have the directive, technology, and machine to run multiple test instances.
         # Experimentation says that reftests are not overly CPU-intensive, so we can run
         # multiple jobs per CPU core.
         #
         # Our Windows machines in automation seem to get upset when we run a lot of
@@ -434,23 +424,30 @@ class RefTest(object):
         if sys.platform == 'win32':
             jobsWithoutFocus = cpuCount
         else:
             jobsWithoutFocus = 2 * cpuCount
 
         totalJobs = jobsWithoutFocus + 1
         perProcessArgs = [sys.argv[:] for i in range(0, totalJobs)]
 
+        host = 'localhost'
+        port = 2828
+        if options.marionette:
+            host, port = options.marionette.split(':')
+
         # First job is only needs-focus tests.  Remaining jobs are
         # non-needs-focus and chunked.
         perProcessArgs[0].insert(-1, "--focus-filter-mode=needs-focus")
         for (chunkNumber, jobArgs) in enumerate(perProcessArgs[1:], start=1):
             jobArgs[-1:-1] = ["--focus-filter-mode=non-needs-focus",
                               "--total-chunks=%d" % jobsWithoutFocus,
-                              "--this-chunk=%d" % chunkNumber]
+                              "--this-chunk=%d" % chunkNumber,
+                              "--marionette=%s:%d" % (host, port)]
+            port += 1
 
         for jobArgs in perProcessArgs:
             try:
                 jobArgs.remove("--run-tests-in-parallel")
             except:
                 pass
             jobArgs[0:0] = [sys.executable, "-u"]
 
@@ -593,16 +590,34 @@ class RefTest(object):
                             cmdargs=cmdargs,
                             env=env,
                             process_args=kp_kwargs)
         runner.start(debug_args=debug_args,
                      interactive=interactive,
                      outputTimeout=timeout)
         proc = runner.process_handler
 
+        if self.use_marionette:
+            marionette_args = { 'symbols_path': options.symbolsPath }
+            if options.marionette:
+                host, port = options.marionette.split(':')
+                marionette_args['host'] = host
+                marionette_args['port'] = int(port)
+
+            marionette = Marionette(**marionette_args)
+            marionette.start_session()
+
+            addons = Addons(marionette)
+            if options.specialPowersExtensionPath:
+                addons.install(options.specialPowersExtensionPath, temp=True)
+
+            addons.install(options.reftestExtensionPath, temp=True)
+
+            marionette.delete_session()
+
         status = runner.wait()
         runner.process_handler = None
 
         if status:
             msg = "TEST-UNEXPECTED-FAIL | %s | application terminated with exit code %s" % \
                 (self.lastTestSeen, status)
             # use process_output so message is logged verbatim
             self.log.process_output(None, msg)
@@ -612,35 +627,39 @@ class RefTest(object):
         crashed = mozcrash.log_crashes(self.log, os.path.join(profile.profile, 'minidumps'),
                                        symbolsPath, test=self.lastTestSeen)
 
         runner.cleanup()
         if not status and crashed:
             status = 1
         return status
 
-    def runSerialTests(self, manifests, options, cmdlineArgs=None):
+    def runSerialTests(self, manifests, options, cmdargs=None):
         debuggerInfo = None
         if options.debugger:
             debuggerInfo = mozdebug.get_debugger_info(options.debugger, options.debuggerArgs,
                                                       options.debuggerInteractive)
 
         profileDir = None
         try:
-            if cmdlineArgs is None:
-                cmdlineArgs = []
+            if cmdargs is None:
+                cmdargs = []
+
+            if self.use_marionette:
+                cmdargs.append('-marionette')
+
             profile = self.createReftestProfile(options, manifests)
             profileDir = profile.profile  # name makes more sense
 
             # browser environment
             browserEnv = self.buildBrowserEnv(options, profileDir)
 
             status = self.runApp(profile,
                                  binary=options.app,
-                                 cmdargs=cmdlineArgs,
+                                 cmdargs=cmdargs,
                                  # give the JS harness 30 seconds to deal with
                                  # its own timeouts
                                  env=browserEnv,
                                  timeout=options.timeout + 30.0,
                                  symbolsPath=options.symbolsPath,
                                  options=options,
                                  debuggerInfo=debuggerInfo)
             mozleak.process_leak_log(self.leakLogFile,
--- a/layout/tools/reftest/runreftestb2g.py
+++ b/layout/tools/reftest/runreftestb2g.py
@@ -47,16 +47,17 @@ class ProfileConfigParser(ConfigParser.R
                 if (value is not None) or (self._optcre == self.OPTCRE):
                     key = "=".join((key, str(value).replace('\n', '\n\t')))
                 fp.write("%s\n" % (key))
             fp.write("\n")
 
 class B2GRemoteReftest(RefTest):
 
     _devicemanager = None
+    use_marionette = False
     localProfile = None
     remoteApp = ''
     profile = None
     resolver_cls = RemoteReftestResolver
 
     def __init__(self, automation, devicemanager, options, scriptDir):
         RefTest.__init__(self)
         self.automation = automation
@@ -320,17 +321,17 @@ class B2GRemoteReftest(RefTest):
                                         debuggerInfo=debuggerInfo,
                                         symbolsPath=symbolsPath,
                                         timeout=timeout,
                                         outputHandler=outputHandler)
         return status
 
 
 def run_remote_reftests(parser, options):
-    auto = B2GRemoteAutomation(None, "fennec", context_chrome=True)
+    auto = B2GRemoteAutomation(None, "fennec")
 
     # create our Marionette instance
     kwargs = {}
     if options.emulator:
         kwargs['emulator'] = options.emulator
         auto.setEmulator(True)
         if options.noWindow:
             kwargs['noWindow'] = True
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1556,17 +1556,22 @@ pref("dom.server-events.enabled", true);
 // Equal to the DEFAULT_RECONNECTION_TIME_VALUE value in nsEventSource.cpp
 pref("dom.server-events.default-reconnection-time", 5000); // in milliseconds
 
 // If false, remote JAR files that are served with a content type other than
 // application/java-archive or application/x-jar will not be opened
 // by the jar channel.
 pref("network.jar.open-unsafe-types", false);
 // If true, loading remote JAR files using the jar: protocol will be prevented.
+#ifdef RELEASE_BUILD
+// Keep allowing remote JAR files for IBM iNotes (see bug 1255139) for now.
+pref("network.jar.block-remote-files", false);
+#else
 pref("network.jar.block-remote-files", true);
+#endif
 
 // This preference, if true, causes all UTF-8 domain names to be normalized to
 // punycode.  The intention is to allow UTF-8 domain names as input, but never
 // generate them from punycode.
 pref("network.IDN_show_punycode", false);
 
 // If "network.IDN.use_whitelist" is set to true, TLDs with
 // "network.IDN.whitelist.tld" explicitly set to true are treated as
--- a/netwerk/base/ProxyAutoConfig.cpp
+++ b/netwerk/base/ProxyAutoConfig.cpp
@@ -317,17 +317,17 @@ void PACLogToConsole(nsString &aMessage)
 
 // Javascript errors are logged to the main error console
 static void
 PACErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
 {
   nsString formattedMessage(NS_LITERAL_STRING("PAC Execution Error: "));
   formattedMessage += report->ucmessage;
   formattedMessage += NS_LITERAL_STRING(" [");
-  formattedMessage += report->uclinebuf;
+  formattedMessage.Append(report->linebuf(), report->linebufLength());
   formattedMessage += NS_LITERAL_STRING("]");
   PACLogToConsole(formattedMessage);
 }
 
 // timeout of 0 means the normal necko timeout strategy, otherwise the dns request
 // will be canceled after aTimeout milliseconds
 static
 bool PACResolve(const nsCString &aHostName, NetAddr *aNetAddr,
--- a/netwerk/cache2/CacheFileIOManager.cpp
+++ b/netwerk/cache2/CacheFileIOManager.cpp
@@ -583,16 +583,17 @@ class OpenFileEvent : public nsRunnable 
 public:
   OpenFileEvent(const nsACString &aKey, uint32_t aFlags,
                 CacheFileIOListener *aCallback)
     : mFlags(aFlags)
     , mCallback(aCallback)
     , mKey(aKey)
   {
     MOZ_COUNT_CTOR(OpenFileEvent);
+    mIOMan = CacheFileIOManager::gInstance;
   }
 
 protected:
   ~OpenFileEvent()
   {
     MOZ_COUNT_DTOR(OpenFileEvent);
   }
 
@@ -602,42 +603,43 @@ public:
     nsresult rv = NS_OK;
 
     if (!(mFlags & CacheFileIOManager::SPECIAL_FILE)) {
       SHA1Sum sum;
       sum.update(mKey.BeginReading(), mKey.Length());
       sum.finish(mHash);
     }
 
-    if (!CacheFileIOManager::gInstance) {
+    if (!mIOMan) {
       rv = NS_ERROR_NOT_INITIALIZED;
     } else {
       if (mFlags & CacheFileIOManager::SPECIAL_FILE) {
-        rv = CacheFileIOManager::gInstance->OpenSpecialFileInternal(
-               mKey, mFlags, getter_AddRefs(mHandle));
+        rv = mIOMan->OpenSpecialFileInternal(mKey, mFlags,
+                                             getter_AddRefs(mHandle));
       } else {
-        rv = CacheFileIOManager::gInstance->OpenFileInternal(
-               &mHash, mKey, mFlags, getter_AddRefs(mHandle));
+        rv = mIOMan->OpenFileInternal(&mHash, mKey, mFlags,
+                                      getter_AddRefs(mHandle));
       }
-
+      mIOMan = nullptr;
       if (mHandle) {
         if (mHandle->Key().IsEmpty()) {
           mHandle->Key() = mKey;
         }
       }
     }
 
     mCallback->OnFileOpened(mHandle, rv);
     return NS_OK;
   }
 
 protected:
   SHA1Sum::Hash                 mHash;
   uint32_t                      mFlags;
   nsCOMPtr<CacheFileIOListener> mCallback;
+  RefPtr<CacheFileIOManager>    mIOMan;
   RefPtr<CacheFileHandle>       mHandle;
   nsCString                     mKey;
 };
 
 class ReadEvent : public nsRunnable {
 public:
   ReadEvent(CacheFileHandle *aHandle, int64_t aOffset, char *aBuf,
             int32_t aCount, CacheFileIOListener *aCallback)
@@ -710,19 +712,18 @@ public:
   NS_IMETHOD Run()
   {
     nsresult rv;
 
     if (mHandle->IsClosed() || (mCallback && mCallback->IsKilled())) {
       // We usually get here only after the internal shutdown
       // (i.e. mShuttingDown == true).  Pretend write has succeeded
       // to avoid any past-shutdown file dooming.
-      rv = (CacheFileIOManager::gInstance &&
-            (CacheFileIOManager::gInstance->IsPastShutdownIOLag() ||
-             CacheFileIOManager::gInstance->mShuttingDown))
+      rv = (CacheFileIOManager::gInstance->IsPastShutdownIOLag() ||
+            CacheFileIOManager::gInstance->mShuttingDown)
         ? NS_OK
         : NS_ERROR_NOT_INITIALIZED;
     } else {
       rv = CacheFileIOManager::gInstance->WriteInternal(
           mHandle, mOffset, mBuf, mCount, mValidate, mTruncate);
       if (NS_FAILED(rv) && !mCallback) {
         // No listener is going to handle the error, doom the file
         CacheFileIOManager::gInstance->DoomFileInternal(mHandle);
@@ -794,45 +795,49 @@ public:
                      CacheFileIOListener *aCallback)
     : mCallback(aCallback)
   {
     MOZ_COUNT_CTOR(DoomFileByKeyEvent);
 
     SHA1Sum sum;
     sum.update(aKey.BeginReading(), aKey.Length());
     sum.finish(mHash);
+
+    mIOMan = CacheFileIOManager::gInstance;
   }
 
 protected:
   ~DoomFileByKeyEvent()
   {
     MOZ_COUNT_DTOR(DoomFileByKeyEvent);
   }
 
 public:
   NS_IMETHOD Run()
   {
     nsresult rv;
 
-    if (!CacheFileIOManager::gInstance) {
+    if (!mIOMan) {
       rv = NS_ERROR_NOT_INITIALIZED;
     } else {
-      rv = CacheFileIOManager::gInstance->DoomFileByKeyInternal(&mHash);
+      rv = mIOMan->DoomFileByKeyInternal(&mHash);
+      mIOMan = nullptr;
     }
 
     if (mCallback) {
       mCallback->OnFileDoomed(nullptr, rv);
     }
 
     return NS_OK;
   }
 
 protected:
   SHA1Sum::Hash                 mHash;
   nsCOMPtr<CacheFileIOListener> mCallback;
+  RefPtr<CacheFileIOManager>    mIOMan;
 };
 
 class ReleaseNSPRHandleEvent : public nsRunnable {
 public:
   explicit ReleaseNSPRHandleEvent(CacheFileHandle *aHandle)
     : mHandle(aHandle)
   {
     MOZ_COUNT_CTOR(ReleaseNSPRHandleEvent);
@@ -1042,21 +1047,24 @@ class MetadataWriteScheduleEvent : publi
 public:
   enum EMode {
     SCHEDULE,
     UNSCHEDULE,
     SHUTDOWN
   } mMode;
 
   RefPtr<CacheFile> mFile;
-
-  MetadataWriteScheduleEvent(CacheFile * aFile,
+  RefPtr<CacheFileIOManager> mIOMan;
+
+  MetadataWriteScheduleEvent(CacheFileIOManager * aManager,
+                             CacheFile * aFile,
                              EMode aMode)
     : mMode(aMode)
     , mFile(aFile)
+    , mIOMan(aManager)
   { }
 
   virtual ~MetadataWriteScheduleEvent() { }
 
   NS_IMETHOD Run()
   {
     RefPtr<CacheFileIOManager> ioMan = CacheFileIOManager::gInstance;
     if (!ioMan) {
@@ -1153,46 +1161,46 @@ CacheFileIOManager::Shutdown()
   gInstance->mShutdownDemanded = true;
 
   Telemetry::AutoTimer<Telemetry::NETWORK_DISK_CACHE_SHUTDOWN_V2> shutdownTimer;
 
   CacheIndex::PreShutdown();
 
   ShutdownMetadataWriteScheduling();
 
-  RefPtr<CacheFileIOManager> ioMan = gInstance;
-
   {
     mozilla::Mutex lock("CacheFileIOManager::Shutdown() lock");
     mozilla::CondVar condVar(lock, "CacheFileIOManager::Shutdown() condVar");
 
     MutexAutoLock autoLock(lock);
     RefPtr<ShutdownEvent> ev = new ShutdownEvent(&lock, &condVar);
     DebugOnly<nsresult> rv;
     nsCOMPtr<nsIEventTarget> ioTarget = gInstance->mIOThread->Target();
     MOZ_ASSERT(ioTarget);
     rv = ioTarget->Dispatch(ev, nsIEventTarget::DISPATCH_NORMAL);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
     condVar.Wait();
-    MOZ_ASSERT(!gInstance);
-  }
-
-  MOZ_ASSERT(ioMan->mHandles.HandleCount() == 0);
-  MOZ_ASSERT(ioMan->mHandlesByLastUsed.Length() == 0);
-
-  if (ioMan->mIOThread) {
-    ioMan->mIOThread->Shutdown();
+  }
+
+  MOZ_ASSERT(gInstance->mHandles.HandleCount() == 0);
+  MOZ_ASSERT(gInstance->mHandlesByLastUsed.Length() == 0);
+
+  if (gInstance->mIOThread) {
+    gInstance->mIOThread->Shutdown();
   }
 
   CacheIndex::Shutdown();
 
   if (CacheObserver::ClearCacheOnShutdown()) {
     Telemetry::AutoTimer<Telemetry::NETWORK_DISK_CACHE2_SHUTDOWN_CLEAR_PRIVATE> totalTimer;
-    ioMan->SyncRemoveAllCacheFiles();
-  }
+    gInstance->SyncRemoveAllCacheFiles();
+  }
+
+  RefPtr<CacheFileIOManager> ioMan;
+  ioMan.swap(gInstance);
 
   return NS_OK;
 }
 
 nsresult
 CacheFileIOManager::ShutdownInternal()
 {
   LOG(("CacheFileIOManager::ShutdownInternal() [this=%p]", this));
@@ -1251,19 +1259,16 @@ CacheFileIOManager::ShutdownInternal()
   MOZ_ASSERT(mHandles.HandleCount() == 0);
 
   // Release trash directory enumerator
   if (mTrashDirEnumerator) {
     mTrashDirEnumerator->Close();
     mTrashDirEnumerator = nullptr;
   }
 
-  RefPtr<CacheFileIOManager> ioMan;
-  ioMan.swap(gInstance);
-
   return NS_OK;
 }
 
 bool
 CacheFileIOManager::IsPastShutdownIOLag()
 {
 #ifdef DEBUG
   return false;
@@ -1430,17 +1435,17 @@ nsresult
 CacheFileIOManager::ScheduleMetadataWrite(CacheFile * aFile)
 {
   RefPtr<CacheFileIOManager> ioMan = gInstance;
   NS_ENSURE_TRUE(ioMan, NS_ERROR_NOT_INITIALIZED);
 
   NS_ENSURE_TRUE(!ioMan->mShuttingDown, NS_ERROR_NOT_INITIALIZED);
 
   RefPtr<MetadataWriteScheduleEvent> event = new MetadataWriteScheduleEvent(
-    aFile, MetadataWriteScheduleEvent::SCHEDULE);
+    ioMan, aFile, MetadataWriteScheduleEvent::SCHEDULE);
   nsCOMPtr<nsIEventTarget> target = ioMan->IOTarget();
   NS_ENSURE_TRUE(target, NS_ERROR_UNEXPECTED);
   return target->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
 }
 
 nsresult
 CacheFileIOManager::ScheduleMetadataWriteInternal(CacheFile * aFile)
 {
@@ -1472,17 +1477,17 @@ nsresult
 CacheFileIOManager::UnscheduleMetadataWrite(CacheFile * aFile)
 {
   RefPtr<CacheFileIOManager> ioMan = gInstance;
   NS_ENSURE_TRUE(ioMan, NS_ERROR_NOT_INITIALIZED);
 
   NS_ENSURE_TRUE(!ioMan->mShuttingDown, NS_ERROR_NOT_INITIALIZED);
 
   RefPtr<MetadataWriteScheduleEvent> event = new MetadataWriteScheduleEvent(
-    aFile, MetadataWriteScheduleEvent::UNSCHEDULE);
+    ioMan, aFile, MetadataWriteScheduleEvent::UNSCHEDULE);
   nsCOMPtr<nsIEventTarget> target = ioMan->IOTarget();
   NS_ENSURE_TRUE(target, NS_ERROR_UNEXPECTED);
   return target->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
 }
 
 nsresult
 CacheFileIOManager::UnscheduleMetadataWriteInternal(CacheFile * aFile)
 {
@@ -1502,17 +1507,17 @@ CacheFileIOManager::UnscheduleMetadataWr
 // static
 nsresult
 CacheFileIOManager::ShutdownMetadataWriteScheduling()
 {
   RefPtr<CacheFileIOManager> ioMan = gInstance;
   NS_ENSURE_TRUE(ioMan, NS_ERROR_NOT_INITIALIZED);
 
   RefPtr<MetadataWriteScheduleEvent> event = new MetadataWriteScheduleEvent(
-    nullptr, MetadataWriteScheduleEvent::SHUTDOWN);
+    ioMan, nullptr, MetadataWriteScheduleEvent::SHUTDOWN);
   nsCOMPtr<nsIEventTarget> target = ioMan->IOTarget();
   NS_ENSURE_TRUE(target, NS_ERROR_UNEXPECTED);
   return target->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
 }
 
 nsresult
 CacheFileIOManager::ShutdownMetadataWriteSchedulingInternal()
 {
--- a/python/mach/mach/registrar.py
+++ b/python/mach/mach/registrar.py
@@ -94,32 +94,33 @@ class MachRegistrar(object):
 
         if context:
             postrun = getattr(context, 'post_dispatch_handler', None)
             if postrun:
                 postrun(context, handler, args=kwargs)
 
         return result
 
-    def dispatch(self, name, context=None, argv=None, **kwargs):
+    def dispatch(self, name, context=None, argv=None, subcommand=None, **kwargs):
         """Dispatch/run a command.
 
         Commands can use this to call other commands.
         """
-        # TODO handler.subcommand_handlers are ignored
         handler = self.command_handlers[name]
 
+        if subcommand:
+            handler = handler.subcommand_handlers[subcommand]
+
         if handler.parser:
             parser = handler.parser
 
             # save and restore existing defaults so **kwargs don't persist across
             # subsequent invocations of Registrar.dispatch()
             old_defaults = parser._defaults.copy()
             parser.set_defaults(**kwargs)
             kwargs, _ = parser.parse_known_args(argv or [])
             kwargs = vars(kwargs)
             parser._defaults = old_defaults
 
         return self._run_command_handler(handler, context=context, **kwargs)
 
 
-
 Registrar = MachRegistrar()
--- a/testing/docker/desktop-test/bin/test.sh
+++ b/testing/docker/desktop-test/bin/test.sh
@@ -10,21 +10,29 @@ set -x -e
 # TODO: when bug 1093833 is solved and tasks can run as non-root, reduce this
 # to a simple fail-if-root check
 if [ $(id -u) = 0 ]; then
     chown -R worker:worker /home/worker
     # drop privileges by re-running this script
     exec sudo -E -u worker bash /home/worker/bin/test.sh "${@}"
 fi
 
+fail() {
+    echo # make sure error message is on a new line
+    echo "[test.sh:error]" "${@}"
+    exit 1
+}
+
 ####
 # Now get the test-linux.sh script from the given Gecko tree and run it with
 # the same arguments.
 ####
 
 [ -d $WORKSPACE ] || mkdir -p $WORKSPACE
 cd $WORKSPACE
 
 script=testing/taskcluster/scripts/tester/test-linux.sh
 url=${GECKO_HEAD_REPOSITORY}/raw-file/${GECKO_HEAD_REV}/${script}
-curl --fail -o ./test-linux.sh --retry 10 $url
+if ! curl --fail -o ./test-linux.sh --retry 10 $url; then
+    fail "failed downloading test-linux.sh from ${GECKO_HEAD_REPOSITORY}"
+fi
 chmod +x ./test-linux.sh
 exec ./test-linux.sh "${@}"
--- a/testing/mochitest/tests/SimpleTest/SimpleTest.js
+++ b/testing/mochitest/tests/SimpleTest/SimpleTest.js
@@ -787,17 +787,17 @@ SimpleTest.waitForFocus = function (call
           }
 
           focusedOrLoaded(null);
       }
 
       if (isChildProcess) {
           /* This message is used when an inner child frame must be focused. */
           addMessageListener("WaitForFocus:FocusChild", function focusChild(msg) {
-              removeMessageListener("WaitForFocus:ChildFocused", focusChild);
+              removeMessageListener("WaitForFocus:FocusChild", focusChild);
               finished = false;
               waitForLoadAndFocusOnWindow(msg.objects.child);
           });
       }
 
       waitForLoadAndFocusOnWindow(targetWindow);
     }
 
@@ -844,16 +844,17 @@ SimpleTest.waitForFocus = function (call
         browser.messageManager.addMessageListener("WaitForFocus:ChildFocused", function waitTest(msg) {
             if (mustFocusSubframe) {
                 mustFocusSubframe = false;
                 var mm = gBrowser.selectedBrowser.messageManager;
                 mm.sendAsyncMessage("WaitForFocus:FocusChild", {}, { child: targetWindow } );
             }
             else {
                 browser.messageManager.removeMessageListener("WaitForFocus:ChildFocused", waitTest);
+                SimpleTest._pendingWaitForFocusCount--;
                 setTimeout(callback, 0, browser ? browser.contentWindowAsCPOW : targetWindow);
             }
         });
 
         // Serialize the waitForFocusInner function and run it in the child process.
         var frameScript = "data:,(" + waitForFocusInner.toString() +
                           ")(content, true, " + expectBlankPage + ");";
         browser.messageManager.loadFrameScript(frameScript, true);
new file mode 100644
--- /dev/null
+++ b/testing/mozharness/configs/android/android_panda_releng.py
@@ -0,0 +1,232 @@
+# This is a template config file for panda android tests on production.
+import socket
+import os
+
+MINIDUMP_STACKWALK_PATH = "/builds/minidump_stackwalk"
+
+config = {
+    # Values for the foopies
+    "exes": {
+        'python': '/tools/buildbot/bin/python',
+        'virtualenv': ['/tools/buildbot/bin/python', '/tools/misc-python/virtualenv.py'],
+    },
+    "hostutils_url":  "http://talos-remote.pvt.build.mozilla.org/tegra/tegra-host-utils.Linux.1109310.2.zip",
+    "verify_path":  "/builds/sut_tools/verify.py",
+    "install_app_path":  "/builds/sut_tools/installApp.py",
+    "logcat_path":  "/builds/sut_tools/logcat.py",
+    "all_mochitest_suites": {
+        "mochitest-1": ["--total-chunks=8", "--this-chunk=1"],
+        "mochitest-2": ["--total-chunks=8", "--this-chunk=2"],
+        "mochitest-3": ["--total-chunks=8", "--this-chunk=3"],
+        "mochitest-4": ["--total-chunks=8", "--this-chunk=4"],
+        "mochitest-5": ["--total-chunks=8", "--this-chunk=5"],
+        "mochitest-6": ["--total-chunks=8", "--this-chunk=6"],
+        "mochitest-7": ["--total-chunks=8", "--this-chunk=7"],
+        "mochitest-8": ["--total-chunks=8", "--this-chunk=8"],
+        "mochitest-gl": ["--subsuite=webgl"],
+    },
+    "all_reftest_suites": {
+        "reftest-1": ["--total-chunks=8", "--this-chunk=1"],
+        "reftest-2": ["--total-chunks=8", "--this-chunk=2"],
+        "reftest-3": ["--total-chunks=8", "--this-chunk=3"],
+        "reftest-4": ["--total-chunks=8", "--this-chunk=4"],
+        "reftest-5": ["--total-chunks=8", "--this-chunk=5"],
+        "reftest-6": ["--total-chunks=8", "--this-chunk=6"],
+        "reftest-7": ["--total-chunks=8", "--this-chunk=7"],
+        "reftest-8": ["--total-chunks=8", "--this-chunk=8"],
+    },
+    "all_crashtest_suites": {
+        "crashtest": []
+    },
+    "all_jsreftest_suites": {
+        "jsreftest-1": ["--total-chunks=3", "--this-chunk=1"],
+        "jsreftest-2": ["--total-chunks=3", "--this-chunk=2"],
+        "jsreftest-3": ["--total-chunks=3", "--this-chunk=3"],
+    },
+    "all_robocop_suites": {
+        "robocop-1": ["--total-chunks=10", "--this-chunk=1"],
+        "robocop-2": ["--total-chunks=10", "--this-chunk=2"],
+        "robocop-3": ["--total-chunks=10", "--this-chunk=3"],
+        "robocop-4": ["--total-chunks=10", "--this-chunk=4"],
+        "robocop-5": ["--total-chunks=10", "--this-chunk=5"],
+        "robocop-6": ["--total-chunks=10", "--this-chunk=6"],
+        "robocop-7": ["--total-chunks=10", "--this-chunk=7"],
+        "robocop-8": ["--total-chunks=10", "--this-chunk=8"],
+        "robocop-9": ["--total-chunks=10", "--this-chunk=9"],
+        "robocop-10": ["--total-chunks=10", "--this-chunk=10"],
+    },
+    "all_instrumentation_suites": {
+        "browser": ["--suite", "browser"],
+        "background": ["--suite", "background"],
+    },
+    "all_xpcshell_suites": {
+        "xpcshell": []
+    },
+    "all_jittest_suites": {
+        "jittest": []
+    },
+    "all_cppunittest_suites": {
+        "cppunittest": ['cppunittest']
+    },
+    "find_links": [
+        "http://pypi.pvt.build.mozilla.org/pub",
+        "http://pypi.pub.build.mozilla.org/pub",
+    ],
+    "suite_definitions": {
+        "cppunittest": {
+            "options": [
+                "--symbols-path=%(symbols_path)s",
+                "--xre-path=tests/bin",
+                "--dm_trans=sut",
+                "--deviceIP=%(device_ip)s",
+                "--localBinDir=../tests/bin",
+                "--apk=%(apk_path)s",
+                "--skip-manifest=../tests/cppunittests/android_cppunittest_manifest.txt"
+            ],
+            "run_filename": "remotecppunittests.py",
+            "testsdir": "cppunittest"
+        },
+        "crashtest": {
+            "options": [
+                "--deviceIP=%(device_ip)s",
+                "--xre-path=../hostutils/xre",
+                "--utility-path=../hostutils/bin",
+                "--app=%(app_name)s",
+                "--ignore-window-size",
+                "--http-port=%(http_port)s",
+                "--ssl-port=%(ssl_port)s",
+                "--symbols-path=%(symbols_path)s",
+                "--suite=crashtest",
+            ],
+            "tests": ["reftest/tests/testing/crashtest/crashtests.list",],
+            "run_filename": "remotereftest.py",
+            "testsdir": "reftest"
+        },
+        "jittest": {
+            "options": [
+                "bin/js",
+                "--remote",
+                "-j",
+                "1",
+                "--deviceTransport=sut",
+                "--deviceIP=%(device_ip)s",
+                "--localLib=../tests/bin",
+                "--no-slow",
+                "--no-progress",
+                "--format=automation",
+                "--jitflags=all"
+            ],
+            "run_filename": "jit_test.py",
+            "testsdir": "jit-test/jit-test"
+        },
+        "jsreftest": {
+            "options": [
+                "--deviceIP=%(device_ip)s",
+                "--xre-path=../hostutils/xre",
+                "--utility-path=../hostutils/bin",
+                "--app=%(app_name)s",
+                "--ignore-window-size",
+                "--extra-profile-file=jsreftest/tests/user.js",
+                "--http-port=%(http_port)s",
+                "--ssl-port=%(ssl_port)s",
+                "--symbols-path=%(symbols_path)s",
+                "--suite=jstestbrowser",
+            ],
+            "tests": ["jsreftest/tests/jstests.list",],
+            "run_filename": "remotereftest.py",
+            "testsdir": "reftest"
+        },
+        "mochitest": {
+            "options": [
+                "--dm_trans=sut",
+                "--deviceIP=%(device_ip)s",
+                "--xre-path=../hostutils/xre",
+                "--utility-path=../hostutils/bin",
+                "--certificate-path=certs",
+                "--app=%(app_name)s",
+                "--http-port=%(http_port)s",
+                "--ssl-port=%(ssl_port)s",
+                "--symbols-path=%(symbols_path)s",
+                "--quiet",
+                "--log-raw=%(raw_log_file)s",
+                "--log-errorsummary=%(error_summary_file)s",
+                "--extra-profile-file=mochitest/fonts",
+                "--screenshot-on-fail",
+            ],
+            "run_filename": "runtestsremote.py",
+            "testsdir": "mochitest"
+        },
+        "reftest": {
+            "options": [
+                "--deviceIP=%(device_ip)s",
+                "--xre-path=../hostutils/xre",
+                "--utility-path=../hostutils/bin",
+                "--app=%(app_name)s",
+                "--ignore-window-size",
+                "--http-port=%(http_port)s",
+                "--ssl-port=%(ssl_port)s",
+                "--symbols-path=%(symbols_path)s",
+                "--extra-profile-file=reftest/fonts",
+                "--suite=reftest",
+                "--log-raw=%(raw_log_file)s",
+                "--log-errorsummary=%(error_summary_file)s",
+            ],
+            "tests": ["reftest/tests/layout/reftests/reftest.list"],
+            "run_filename": "remotereftest.py",
+            "testsdir": "reftest"
+        },
+        "robocop": {
+            "options": [
+                "--dm_trans=sut",
+                "--deviceIP=%(device_ip)s",
+                "--xre-path=../hostutils/xre",
+                "--utility-path=../hostutils/bin",
+                "--certificate-path=certs",
+                "--app=%(app_name)s",
+                "--console-level=INFO",
+                "--http-port=%(http_port)s",
+                "--ssl-port=%(ssl_port)s",
+                "--symbols-path=%(symbols_path)s",
+                "--robocop-ini=mochitest/robocop.ini"
+            ],
+            "run_filename": "runrobocop.py",
+            "testsdir": "mochitest"
+        },
+        "xpcshell": {
+            "options": [
+                "--deviceIP=%(device_ip)s",
+                "--xre-path=../hostutils/xre",
+                "--manifest=xpcshell/tests/xpcshell.ini",
+                "--build-info-json=xpcshell/mozinfo.json",
+                "--testing-modules-dir=modules",
+                "--local-lib-dir=../fennec",
+                "--apk=../%(apk_name)s",
+                "--no-logfiles",
+                "--symbols-path=%(symbols_path)s",
+                "--log-raw=%(raw_log_file)s",
+                "--log-errorsummary=%(error_summary_file)s",
+            ],
+            "run_filename": "remotexpcshelltests.py",
+            "testsdir": "xpcshell"
+        }
+    },
+    "pip_index": False,
+    "buildbot_json_path": "buildprops.json",
+    "mobile_imaging_format": "http://mobile-imaging",
+    "mozpool_assignee": socket.gethostname(),
+    "default_actions": [
+        'clobber',
+        'read-buildbot-config',
+        'download-and-extract',
+        'create-virtualenv',
+        'request-device',
+        'run-test',
+        'close-request',
+    ],
+    "minidump_stackwalk_path": MINIDUMP_STACKWALK_PATH,
+    "minidump_save_path": "%(abs_work_dir)s/../minidumps",
+    "default_blob_upload_servers": [
+         "https://blobupload.elasticbeanstalk.com",
+    ],
+    "blob_uploader_auth_file" : os.path.join(os.getcwd(), "oauth.txt"),
+}
--- a/testing/mozharness/configs/android/androidarm.py
+++ b/testing/mozharness/configs/android/androidarm.py
@@ -147,17 +147,16 @@ config = {
             ],
         },
         "reftest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--deviceIP=%(device_ip)s",
                 "--devicePort=%(device_port)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path",
@@ -172,17 +171,16 @@ config = {
             "tests": ["tests/layout/reftests/reftest.list"],
         },
         "crashtest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--deviceIP=%(device_ip)s",
                 "--devicePort=%(device_port)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path",
@@ -194,17 +192,16 @@ config = {
             "tests": ["tests/testing/crashtest/crashtests.list"],
         },
         "jsreftest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--deviceIP=%(device_ip)s",
                 "--devicePort=%(device_port)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path",
--- a/testing/mozharness/configs/android/androidarm_4_3.py
+++ b/testing/mozharness/configs/android/androidarm_4_3.py
@@ -146,17 +146,16 @@ config = {
         },
         "reftest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path", "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
                 "--total-chunks=16",
@@ -169,17 +168,16 @@ config = {
         },
         "reftest-debug": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path", "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
                 "--total-chunks=48",
@@ -189,17 +187,16 @@ config = {
         },
         "crashtest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path",
                 "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
@@ -210,17 +207,16 @@ config = {
         },
         "crashtest-debug": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s",
                 "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s",
                 "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s",
                 "--httpd-path",
                 "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
@@ -230,17 +226,16 @@ config = {
         },
         "jsreftest": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s", "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s", "--httpd-path", "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
                 "--total-chunks=6",
                 "--extra-profile-file=jsreftest/tests/user.js",
                 "--suite=jstestbrowser",
             ],
@@ -248,17 +243,16 @@ config = {
         },
         "jsreftest-debug": {
             "run_filename": "remotereftest.py",
             "testsdir": "reftest",
             "options": [
                 "--app=%(app)s",
                 "--ignore-window-size",
                 "--dm_trans=adb",
-                "--bootstrap",
                 "--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s",
                 "--utility-path=%(utility_path)s", "--http-port=%(http_port)s",
                 "--ssl-port=%(ssl_port)s", "--httpd-path", "%(modules_dir)s",
                 "--symbols-path=%(symbols_path)s",
                 "../jsreftest/tests/jstests.list",
                 "--total-chunks=20",
                 "--extra-profile-file=jsreftest/tests/user.js",
             ],
--- a/testing/mozharness/configs/android/androidx86.py
+++ b/testing/mozharness/configs/android/androidx86.py
@@ -87,17 +87,16 @@ config = {
                         "--log-errorsummary=%(error_summary_file)s",
                         "--screenshot-on-fail",
                     ],
         },
         "reftest": {
             "run_filename": "remotereftest.py",
             "options": ["--app=%(app)s",
                         "--ignore-window-size",
-                        "--bootstrap",
                         "--remote-webserver=%(remote_webserver)s",
                         "--xre-path=%(xre_path)s",
                         "--utility-path=%(utility_path)s",
                         "--http-port=%(http_port)s",
                         "--ssl-port=%(ssl_port)s",
                         "--httpd-path", "%(modules_dir)s",
                         "--symbols-path=%(symbols_path)s",
                     ],
--- a/testing/taskcluster/scripts/builder/build-linux.sh
+++ b/testing/taskcluster/scripts/builder/build-linux.sh
@@ -23,31 +23,37 @@ echo "running as" $(id)
 
 : WORKSPACE                     ${WORKSPACE:=/home/worker/workspace}
 
 # some linux variants, e.g. b2gdroid, require gaia
 : CHECKOUT_GAIA                      ${CHECKOUT_GAIA:=false}
 
 set -v
 
+fail() {
+    echo # make sure error message is on a new line
+    echo "[build-linux.sh:error]" "${@}"
+    exit 1
+}
+
 export MOZ_CRASHREPORTER_NO_REPORT=1
 export MOZ_OBJDIR=obj-firefox
 export MOZ_SYMBOLS_EXTRA_BUILDID=linux64
 export TINDERBOX_OUTPUT=1
 
 # use "simple" package names so that they can be hard-coded in the task's
 # extras.locations
 export MOZ_SIMPLE_PACKAGE_NAME=target
 
 # Ensure that in tree libraries can be found
 export LIBRARY_PATH=$LIBRARY_PATH:$WORKSPACE/src/obj-firefox:$WORKSPACE/src/gcc/lib64
 
 # test required parameters are supplied
-if [[ -z ${MOZHARNESS_SCRIPT} ]]; then exit 1; fi
-if [[ -z ${MOZHARNESS_CONFIG} ]]; then exit 1; fi
+if [[ -z ${MOZHARNESS_SCRIPT} ]]; then fail "MOZHARNESS_SCRIPT is not set"; fi
+if [[ -z ${MOZHARNESS_CONFIG} ]]; then fail "MOZHARNESS_CONFIG is not set"; fi
 
 cleanup() {
     local rv=$?
     if [ -n "$xvfb_pid" ]; then
         kill $xvfb_pid || true
     fi
     exit $rv
 }
@@ -69,18 +75,19 @@ if $NEED_XVFB; then
     until [ $retry_count -gt $max_retries ]; do
         xvinfo || xvfb_test=$?
         if [ $xvfb_test != 255 ]; then
             retry_count=$(($max_retries + 1))
         else
             retry_count=$(($retry_count + 1))
             echo "Failed to start Xvfb, retry: $retry_count"
             sleep 2
-        fi done
-    if [ $xvfb_test == 255 ]; then exit 255; fi
+        fi
+    done
+    if [ $xvfb_test == 255 ]; then fail "xvfb did not start properly"; fi
 fi
 
 # set up mozharness configuration, via command line, env, etc.
 
 debug_flag=""
 if [ 0$DEBUG -ne 0 ]; then
   debug_flag='--debug'
 fi
--- a/testing/taskcluster/scripts/tester/test-linux.sh
+++ b/testing/taskcluster/scripts/tester/test-linux.sh
@@ -19,20 +19,26 @@ echo "running as" $(id)
 : START_VNC                     ${START_VNC:=false}
 : SKIP_MOZHARNESS_RUN           ${SKIP_MOZHARNESS_RUN:=false}
 : WORKSPACE                     ${WORKSPACE:=/home/worker/workspace}
 : mozharness args               "${@}"
 
 set -v
 cd $WORKSPACE
 
+fail() {
+    echo # make sure error message is on a new line
+    echo "[test-linux.sh:error]" "${@}"
+    exit 1
+}
+
 # test required parameters are supplied
-if [[ -z ${MOZHARNESS_URL} ]]; then exit 1; fi
-if [[ -z ${MOZHARNESS_SCRIPT} ]]; then exit 1; fi
-if [[ -z ${MOZHARNESS_CONFIG} ]]; then exit 1; fi
+if [[ -z ${MOZHARNESS_URL} ]]; then fail "MOZHARNESS_URL is not set"; fi
+if [[ -z ${MOZHARNESS_SCRIPT} ]]; then fail "MOZHARNESS_SCRIPT is not set"; fi
+if [[ -z ${MOZHARNESS_CONFIG} ]]; then fail "MOZHARNESS_CONFIG is not set"; fi
 
 mkdir -p ~/artifacts/public
 
 cleanup() {
     local rv=$?
     if [[ -s /home/worker/.xsession-errors ]]; then
       # To share X issues
       cp /home/worker/.xsession-errors ~/artifacts/public/xsession-errors.log
@@ -42,24 +48,25 @@ cleanup() {
     if [ -n "$xvfb_pid" ] && [ $START_VNC == false ] ; then
         kill $xvfb_pid || true
     fi
     exit $rv
 }
 trap cleanup EXIT INT
 
 # Unzip the mozharness ZIP file created by the build task
-curl --fail -o mozharness.zip --retry 10 -L $MOZHARNESS_URL
+if ! curl --fail -o mozharness.zip --retry 10 -L $MOZHARNESS_URL; then
+    fail "failed to download mozharness zip"
+fi
 rm -rf mozharness
 unzip -q mozharness.zip
 rm mozharness.zip
 
 if ! [ -d mozharness ]; then
-    echo "mozharness zip did not contain mozharness/"
-    exit 1
+    fail "mozharness zip did not contain mozharness/"
 fi
 
 # start up the pulseaudio daemon.  Note that it's important this occur
 # before the Xvfb startup.
 if $NEED_PULSEAUDIO; then
     pulseaudio --fail --daemonize --start
     pactl load-module module-null-sink
 fi
@@ -80,18 +87,19 @@ if $NEED_XVFB; then
     until [ $retry_count -gt $max_retries ]; do
         xvinfo || xvfb_test=$?
         if [ $xvfb_test != 255 ]; then
             retry_count=$(($max_retries + 1))
         else
             retry_count=$(($retry_count + 1))
             echo "Failed to start Xvfb, retry: $retry_count"
             sleep 2
-        fi done
-    if [ $xvfb_test == 255 ]; then exit 255; fi
+        fi
+    done
+    if [ $xvfb_test == 255 ]; then fail "xvfb did not start properly"; fi
 fi
 
 if $START_VNC; then
     x11vnc > ~/artifacts/public/x11vnc.log 2>&1 &
 fi
 
 if $NEED_WINDOW_MANAGER; then
     # This is read by xsession to select the window manager
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -6818,17 +6818,18 @@ nsWindow::SynthesizeNativeMouseEvent(Lay
 #endif
 
     gdk_event_put(&event);
   } else {
     // We don't support specific events other than button-release. In case
     // aNativeMessage != GDK_BUTTON_RELEASE we'll synthesize a motion event
     // that will be emitted by gdk_display_warp_pointer().
     GdkScreen* screen = gdk_window_get_screen(mGdkWindow);
-    gdk_display_warp_pointer(display, screen, aPoint.x, aPoint.y);
+    GdkPoint point = DevicePixelsToGdkPointRoundDown(aPoint);
+    gdk_display_warp_pointer(display, screen, point.x, point.y);
   }
 
   return NS_OK;
 }
 
 nsresult
 nsWindow::SynthesizeNativeMouseScrollEvent(mozilla::LayoutDeviceIntPoint aPoint,
                                            uint32_t aNativeMessage,
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -2467,18 +2467,19 @@ CCGraphBuilder::NoteWeakMapping(JSObject
   // do that in TraceWeakMapping in nsXPConnect.
   WeakMapping* mapping = mGraph.mWeakMaps.AppendElement();
   mapping->mMap = aMap ? AddWeakMapNode(aMap) : nullptr;
   mapping->mKey = aKey ? AddWeakMapNode(aKey) : nullptr;
   mapping->mKeyDelegate = aKdelegate ? AddWeakMapNode(aKdelegate) : mapping->mKey;
   mapping->mVal = aVal ? AddWeakMapNode(aVal) : nullptr;
 
   if (mLogger) {
-    mLogger->NoteWeakMapEntry((uint64_t)aMap, aKey.unsafeAsInteger(),
-                              (uint64_t)aKdelegate, aVal.unsafeAsInteger());
+    mLogger->NoteWeakMapEntry((uint64_t)aMap, aKey ? aKey.unsafeAsInteger() : 0,
+                              (uint64_t)aKdelegate,
+                              aVal ? aVal.unsafeAsInteger() : 0);
   }
 }
 
 static bool
 AddPurpleRoot(CCGraphBuilder& aBuilder, void* aRoot,
               nsCycleCollectionParticipant* aParti)
 {
   return aBuilder.AddPurpleRoot(aRoot, aParti);