Backed out changeset a845717e4d10 (bug 1482279) for causing multiple failures.
authorMihai Alexandru Michis <malexandru@mozilla.com>
Sat, 23 May 2020 02:22:20 +0300
changeset 531733 d5c77659d412d28268519c1add754776fa566c1c
parent 531732 dbfad8ecbc50101059e071130868498454bc0705
child 531734 c83c52541dd21556eb3afabf64a0960891e17f0d
push id37442
push userncsoregi@mozilla.com
push dateSat, 23 May 2020 09:21:24 +0000
treeherdermozilla-central@bbcc193fe0f0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1482279
milestone78.0a1
backs outa845717e4d10ad7cb65ca64b08666c373db6e1de
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
Backed out changeset a845717e4d10 (bug 1482279) for causing multiple failures. CLOSED TREE
caps/tests/mochitest/test_bug246699.html
devtools/client/shared/test/doc_layoutHelpers_getBoxQuads2-c-and-e.html
dom/animation/test/mozilla/file_restyles.html
dom/animation/test/testcommon.js
dom/bindings/test/test_bug1036214.html
dom/console/tests/test_count.html
dom/console/tests/test_jsm.xhtml
dom/console/tests/test_timer.html
dom/media/tests/mochitest/test_getUserMedia_scarySources.html
dom/quota/test/common/content.js
dom/tests/mochitest/bugs/test_bug61098.html
dom/tests/mochitest/bugs/test_bug850517.html
dom/tests/mochitest/bugs/test_instanceof_error_message.html
dom/tests/mochitest/bugs/test_postmessage.html
dom/workers/test/test_WorkerDebugger_console.xhtml
image/test/mochitest/test_bug671906.html
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/tests/mochitest/chrome_wrappers_helper.html
layout/base/tests/test_bug416896.html
layout/inspector/tests/test_getCSSStyleRules.html
layout/style/test/test_restyles_in_smil_animation.html
testing/mochitest/tests/SimpleTest/MockObjects.js
testing/mochitest/tests/SimpleTest/SimpleTest.js
testing/specialpowers/content/MockColorPicker.jsm
testing/specialpowers/content/MockFilePicker.jsm
testing/specialpowers/content/SpecialPowersChild.jsm
testing/specialpowers/content/WrapPrivileged.jsm
toolkit/components/passwordmgr/test/browser/head.js
toolkit/components/passwordmgr/test/mochitest/test_autofocus_js.html
toolkit/components/passwordmgr/test/mochitest/test_munged_values.html
toolkit/content/tests/widgets/test_ua_widget_sandbox.html
--- a/caps/tests/mochitest/test_bug246699.html
+++ b/caps/tests/mochitest/test_bug246699.html
@@ -41,17 +41,17 @@ function inciteCaps(f) {
     }
 }
 
 function tryChromeLoad() {
     window.frames[0].location = "chrome://global/content/mozilla.xhtml";
 }
 
 function tryComponentsClasses() {
-    return SpecialPowers.unwrap(SpecialPowers.Cc)["@mozilla.org/dummy;1"];
+    return SpecialPowers.Components.classes["@mozilla.org/dummy;1"];
 }
 
 
 is(inciteCaps(tryChromeLoad), "denied-stack",
    "should get stack for content-loading-chrome rejection");
 is(inciteCaps(tryComponentsClasses), "denied-stack",
    "should get stack for SpecialPowers.Components.classes rejection");
 </script>
--- a/devtools/client/shared/test/doc_layoutHelpers_getBoxQuads2-c-and-e.html
+++ b/devtools/client/shared/test/doc_layoutHelpers_getBoxQuads2-c-and-e.html
@@ -1,17 +1,17 @@
 <!doctype html>
 <meta charset=utf-8>
 <script>
 'use strict';
 window.onmessage = event => {
   const innerNode = window.document.getElementById("inner-node");
   const wrappedNode = SpecialPowers.wrap(innerNode);
   const wrappedQuads = wrappedNode.getBoxQuadsFromWindowOrigin();
-  const quad = SpecialPowers.unwrap(wrappedQuads[0]);
+  const [quad] = SpecialPowers.unwrap(wrappedQuads);
 
   window.parent.postMessage({ quad }, "*");
 };
 </script>
 <style>
   body {
     margin: 0;
     padding: 0;
--- a/dom/animation/test/mozilla/file_restyles.html
+++ b/dom/animation/test/mozilla/file_restyles.html
@@ -67,17 +67,17 @@ body {
 // restyles, and returns any restyle markers produced by calling that function.
 function observeAnimSyncStyling(funcToMakeRestyleHappen) {
   const docShell = getDocShellForObservingRestylesForWindow(window);
 
   funcToMakeRestyleHappen();
 
   const markers = docShell.popProfileTimelineMarkers();
   docShell.recordProfileTimelineMarkers = false;
-  return Array.prototype.filter.call(markers, (marker, index) => {
+  return markers.filter((marker, index) => {
     return marker.name == 'Styles' && marker.isAnimationOnly;
   });
 }
 
 function ensureElementRemoval(aElement) {
   return new Promise(resolve => {
     aElement.remove();
     waitForAllPaintsFlushed(resolve);
--- a/dom/animation/test/testcommon.js
+++ b/dom/animation/test/testcommon.js
@@ -516,18 +516,15 @@ function observeStyling(frameCount, onFr
 // As with observeStyling but applied to target window |aWindow|.
 function observeStylingInTargetWindow(aWindow, aFrameCount, aOnFrame) {
   const docShell = getDocShellForObservingRestylesForWindow(aWindow);
 
   return new Promise(resolve => {
     return waitForAnimationFrames(aFrameCount, aOnFrame, aWindow).then(() => {
       const markers = docShell.popProfileTimelineMarkers();
       docShell.recordProfileTimelineMarkers = false;
-      const stylingMarkers = Array.prototype.filter.call(
-        markers,
-        (marker, index) => {
-          return marker.name == "Styles" && marker.isAnimationOnly;
-        }
-      );
+      const stylingMarkers = markers.filter((marker, index) => {
+        return marker.name == "Styles" && marker.isAnimationOnly;
+      });
       resolve(stylingMarkers);
     });
   });
 }
--- a/dom/bindings/test/test_bug1036214.html
+++ b/dom/bindings/test/test_bug1036214.html
@@ -14,18 +14,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   /** Test for subsumes-checking |any| and |object| for js-implemented WebIDL. **/
   SimpleTest.waitForExplicitFinish();
   var xoObjects = [];
   function setup() {
     // window[0] is same-process and cross-origin, even with Fission enabled.
     xoObjects.push(window[0]);
     xoObjects.push(window[0].location);
     xoObjects.push(SpecialPowers.unwrap(SpecialPowers.wrap(window[0]).document));
-    xoObjects.push(SpecialPowers.unwrap(SpecialPowers));
-    xoObjects.push(SpecialPowers.unwrap(SpecialPowers.wrap));
+    xoObjects.push(SpecialPowers);
+    xoObjects.push(SpecialPowers.wrap);
     SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, go);
   }
 
   function setup2() {
     if (SpecialPowers.useRemoteSubframes) {
       // window[1] is cross-origin and out of process, with Fission enabled.
       xoObjects.push(window[1]);
       xoObjects.push(window[1].location);
--- a/dom/console/tests/test_count.html
+++ b/dom/console/tests/test_count.html
@@ -36,17 +36,17 @@ ConsoleListener.prototype = {
   },
 
   shutdown() {
     SpecialPowers.removeObserver(this, "console-api-log-event");
   },
 
   waitFor(cb) {
     return new Promise(resolve => {
-      this._cb = SpecialPowers.wrapCallback(cb);
+      this._cb = cb;
       this._resolve = resolve;
     });
   },
 };
 
 let listener = new ConsoleListener();
 
 async function runTest() {
@@ -101,16 +101,13 @@ async function runTest() {
            obj.counter.label == "test" &&
            obj.counter.count == 1;
   });
   console.count("test");
   await cl;
   ok(true, "Console.count == 1 received!");
 }
 
-runTest().then(() => {
-  listener.shutdown();
-  SimpleTest.finish();
-});
+runTest().then(SimpleTest.finish);
 
   </script>
 </body>
 </html>
--- a/dom/console/tests/test_jsm.xhtml
+++ b/dom/console/tests/test_jsm.xhtml
@@ -10,27 +10,25 @@
   <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
   <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript">
   <![CDATA[
 
 const JSM = "chrome://mochitests/content/chrome/dom/console/tests/console.jsm";
 
-const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-
 let dumpCalled = 0;
 function dumpFunction(msg) {
   ok(msg.includes("_PREFIX_"), "we have a prefix");
   dump("Message received: " + msg); // Just for debugging
   dumpCalled++;
 }
 
 function consoleListener() {
-  Services.obs.addObserver(this, "console-api-log-event");
+  SpecialPowers.addObserver(this, "console-api-log-event");
 }
 
 consoleListener.prototype  = {
   count: 0,
 
   observe: function(aSubject, aTopic, aData) {
     if (aTopic == "console-api-log-event") {
       var obj = aSubject.wrappedJSObject;
@@ -56,17 +54,17 @@ consoleListener.prototype  = {
         is(obj.ID, "jsm", "ID and InnerID are correctly set.");
         is(obj.arguments[0], "Hello world!", "Message matches");
         is(obj.prefix, "", "prefix is empty by default");
         ++this.count;
       }
 
       if (this.count == 4) {
         is(dumpCalled, 2, "Dump has been called!");
-        Services.obs.removeObserver(this, "console-api-log-event");
+        SpecialPowers.removeObserver(this, "console-api-log-event");
         SimpleTest.finish();
       }
     }
   }
 }
 function test() {
   SimpleTest.waitForExplicitFinish();
 
--- a/dom/console/tests/test_timer.html
+++ b/dom/console/tests/test_timer.html
@@ -34,17 +34,17 @@ ConsoleListener.prototype = {
   },
 
   shutdown() {
     SpecialPowers.removeObserver(this, "console-api-log-event");
   },
 
   waitFor(cb) {
     return new Promise(resolve => {
-      this._cb = SpecialPowers.wrapCallback(cb);
+      this._cb = cb;
       this._resolve = resolve;
     });
   },
 };
 
 let listener = new ConsoleListener();
 
 // Timer creation:
--- a/dom/media/tests/mochitest/test_getUserMedia_scarySources.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_scarySources.html
@@ -8,49 +8,46 @@
 <script type="application/javascript">
 
 createHTML({title: "Detect screensharing sources that are firefox", bug: "1311048"});
 
 const { Services } = SpecialPowers.Cu.import('resource://gre/modules/Services.jsm');
 
 let observe = topic => new Promise(r => Services.obs.addObserver(function o(...args) {
   Services.obs.removeObserver(o, topic);
-  r(args.map(x => SpecialPowers.wrap(x)));
+  r(args);
 }, topic));
 
 let getDevices = async constraints => {
   let [{ windowID, innerWindowID, callID }] = await Promise.race([
     getUserMedia(constraints),
     observe("getUserMedia:request")
   ]);
   let window = Services.wm.getOuterWindowWithId(windowID);
-  let devices = await new Promise((resolve, reject) => {
-      resolve = SpecialPowers.wrapCallback(resolve);
-      reject = SpecialPowers.wrapCallback(reject);
+  let devices = await new Promise((resolve, reject) =>
       window.navigator.mozGetUserMediaDevices({}, resolve, reject,
-                                              innerWindowID, callID);
-  });
+                                              innerWindowID, callID));
   return devices.map(SpecialPowers.wrapCallback(d => d.QueryInterface(Ci.nsIMediaDevice)));
 };
 
 runTest(async () => {
   await pushPrefs(["media.navigator.permission.disabled", true],
                   ["media.navigator.permission.fake", true],
                   ["media.navigator.permission.force", true]);
   let devices = await getDevices({video: { mediaSource: "window" }});
   ok(devices.length, "Found one or more windows.");
-  devices = Array.prototype.filter.call(devices, d => d.scary);
+  devices = devices.filter(d => d.scary);
   ok(devices.length, "Found one or more scary windows (our own counts).");
   devices.filter(d => d.name.includes("MochiTest"));
   ok(devices.length,
      "Our own window is among the scary: " + devices.map(d => `"${d.name}"`));
 
   devices = await getDevices({video: { mediaSource: "screen" }});
   let numScreens = devices.length;
   ok(numScreens, "Found one or more screens.");
-  devices = Array.prototype.filter.call(devices, d => d.scary);
+  devices = devices.filter(d => d.scary);
   is(devices.length, numScreens, "All screens are scary.");
 });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/quota/test/common/content.js
+++ b/dom/quota/test/common/content.js
@@ -43,15 +43,29 @@ function getSimpleDatabase() {
 
   return connection;
 }
 
 function requestFinished(request) {
   return new Promise(function(resolve, reject) {
     request.callback = SpecialPowers.wrapCallback(function(req) {
       if (req.resultCode === SpecialPowers.Cr.NS_OK) {
-        resolve(req.result);
+        let result = req.result;
+        if (
+          SpecialPowers.call_Instanceof(result, SpecialPowers.Ci.nsISDBResult)
+        ) {
+          let wrapper = {};
+          for (let i in result) {
+            if (typeof result[i] == "function") {
+              wrapper[i] = SpecialPowers.unwrap(result[i]);
+            } else {
+              wrapper[i] = result[i];
+            }
+          }
+          result = wrapper;
+        }
+        resolve(result);
       } else {
         reject(req.resultCode);
       }
     });
   });
 }
--- a/dom/tests/mochitest/bugs/test_bug61098.html
+++ b/dom/tests/mochitest/bugs/test_bug61098.html
@@ -59,53 +59,53 @@ function registerMockPromptService()
       winUtils.enterModalState();
       winUtils.leaveModalState();
     },
 
     alert(aDialogTitle, aText)
     {
       this._toggleModalState();
       promptState = {method: "alert",
-                     parent: SpecialPowers.unwrap(this.domWindow),
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText
       };
     },
 
     alertCheck(aDialogTitle, aText, aCheckMsg, aCheckState)
     {
       this._toggleModalState();
       promptState = {method: "alertCheck",
-                     parent: SpecialPowers.unwrap(this.domWindow),
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText,
                      checkMsg: aCheckMsg,
                      checkState: aCheckState
       };
 
       SpecialPowers.wrap(aCheckState).value = true;
     },
 
     confirm(aDialogTitle, aText)
     {
       this._toggleModalState();
       promptState = {method: "confirm",
-                     parent: SpecialPowers.unwrap(this.domWindow),
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText
       };
 
       return true;
     },
 
     confirmCheck(aDialogTitle, aText, aCheckMsg, aCheckState)
     {
       this._toggleModalState();
       promptState = {method: "confirmCheck",
-                     parent: SpecialPowers.unwrap(this.domWindow),
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText,
                      checkMsg: aCheckMsg,
                      checkState: aCheckState
       };
 
       SpecialPowers.wrap(aCheckState).value = true;
 
@@ -113,17 +113,17 @@ function registerMockPromptService()
     },
 
     confirmEx(aDialogTitle, aText, aButtonFlags,
                         aButton0Title, aButton1Title, aButton2Title,
                         aCheckMsg, aCheckState)
     {
       this._toggleModalState();
       promptState = {method: "confirmCheck",
-                     parent: SpecialPowers.unwrap(this.domWindow),
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText,
                      checkMsg: aCheckMsg,
                      checkState: aCheckState
       };
 
       if (aCheckMsg != null)
         SpecialPowers.wrap(aCheckState).value = true;
@@ -131,17 +131,17 @@ function registerMockPromptService()
       return 0;
     },
 
     prompt(aDialogTitle, aText, aValue, aCheckMsg,
                      aCheckState)
     {
       this._toggleModalState();
       promptState = {method: "prompt",
-                     parent: SpecialPowers.unwrap(this.domWindow),
+                     parent: this.domWindow,
                      title: aDialogTitle,
                      msg: aText,
                      checkMsg: aCheckMsg,
                      checkState: aCheckState
       };
 
       if (aCheckMsg != null)
         SpecialPowers.wrap(aCheckState).value = true;
@@ -163,17 +163,17 @@ function registerMockPromptService()
       if (iid.equals(Ci.nsIPromptFactory) || iid.equals(Ci.nsIPromptService)) {
         return this;
       }
       throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
     },
 
     getPrompt(aDOMWindow, aIID)
     {
-        return SpecialPowers.wrapCallbackObject(new MockPrompt(aDOMWindow));
+        return new MockPrompt(aDOMWindow);
     },
 
     alert(aParent, aDialogTitle, aText)
     {
       var prompt = new MockPrompt(aParent);
       return prompt.alert(aDialogTitle, aText);
     },
 
--- a/dom/tests/mochitest/bugs/test_bug850517.html
+++ b/dom/tests/mochitest/bugs/test_bug850517.html
@@ -15,18 +15,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   function go() {
     var ifrA = $('a');
     var ifrB = $('b');
     var sb = new SpecialPowers.Cu.Sandbox('http://www.example.com');
     sb.win = window;
     sb.childA = ifrA.contentWindow;
     sb.childB = ifrB.contentWindow;
-    SpecialPowers.setWrapped(sb, 'is', SpecialPowers.wrapFor(is, sb));
-    SpecialPowers.setWrapped(sb, 'ok', SpecialPowers.wrapFor(ok, sb));
+    SpecialPowers.setWrapped(sb, 'is', SpecialPowers.wrap(is));
+    SpecialPowers.setWrapped(sb, 'ok', SpecialPowers.wrap(ok));
     is(window.theoneandonly.frameElement, ifrA, "Named child resolution works");
     SpecialPowers.Cu.evalInSandbox('is(win.theoneandonly, childA, "Named child resolution works via Xray");', sb);
     ifrA.removeAttribute('name');
     is(typeof window.theoneandonly, 'undefined', "Revocation works");
     SpecialPowers.Cu.evalInSandbox('try { win.theoneandonly; ok(false, "Should have thrown"); } ' +
                                    'catch (e) {ok(!!/denied/.exec(e) && !!/theoneandonly/.exec(e), "Revocation works via Xray");};', sb);
     ifrB.setAttribute('name', 'theoneandonly');
     is(window.theoneandonly.frameElement, ifrB, "Another mule kicking in the same old stall");
--- a/dom/tests/mochitest/bugs/test_instanceof_error_message.html
+++ b/dom/tests/mochitest/bugs/test_instanceof_error_message.html
@@ -80,17 +80,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     }
     delete window[Symbol.hasInstance];
     Cu.nukeSandbox(sandbox);
 
     // Test case 8 - Test instanceof with RHS being a same-origin Xray waiver
     sandbox = SpecialPowers.unwrap(Cu.Sandbox(this, { sameZoneAs: this, freshCompartment: true}));
     sandbox.window = window;
     sandbox.crossCompartmentObject = {};
-    sandbox.waiveXrays = SpecialPowers.wrapFor(Cu.waiveXrays, sandbox);
+    sandbox.waiveXrays = Cu.waiveXrays;
 
     window[Symbol.hasInstance] = function(instance) {
       instance.window = this;
       return true;
     }
     Cu.evalInSandbox("(crossCompartmentObject instanceof waiveXrays(window));", sandbox);
     ok(x, "Symbol.hasInstance for window should return true");
     is(sandbox.crossCompartmentObject.window, window,
--- a/dom/tests/mochitest/bugs/test_postmessage.html
+++ b/dom/tests/mochitest/bugs/test_postmessage.html
@@ -25,17 +25,17 @@
         });
       });
     });
   }
   add_task(async function testNoCallerURI() {
     var Cu = SpecialPowers.Cu;
     var princ = SpecialPowers.wrap(window.document).nodePrincipal;
     var sandbox = Cu.Sandbox(princ, { sameZoneAs: this });
-    SpecialPowers.unwrap(sandbox).win = window.frames.diffDomain;
+    sandbox.win = window.frames.diffDomain;
     var err = `Failed to execute ‘postMessage’ on ‘DOMWindow’: The target origin provided (‘https://example.com’) does not match the recipient window’s origin (‘https://example.org’).`;
     let consolePromise = waitForErrorMessage(err);
     Cu.evalInSandbox(
       'win.postMessage("We should not be able to post this message", "https://example.com");',
       sandbox
     );
     await consolePromise;
     ok(true, "Error message was logged correctly to the console");
--- a/dom/workers/test/test_WorkerDebugger_console.xhtml
+++ b/dom/workers/test/test_WorkerDebugger_console.xhtml
@@ -13,33 +13,31 @@
 
   <script type="application/javascript">
   <![CDATA[
 
     const WORKER_URL = "WorkerDebugger.console_worker.js";
     const CHILD_WORKER_URL = "WorkerDebugger.console_childWorker.js";
     const DEBUGGER_URL = BASE_URL + "WorkerDebugger.console_debugger.js";
 
-    const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-
     consoleMessagesReceived = 0;
     function test() {
       function consoleListener() {
-        Services.obs.addObserver(this, "console-api-log-event");
+        SpecialPowers.addObserver(this, "console-api-log-event");
       }
 
       consoleListener.prototype  = {
         observe: function(aSubject, aTopic, aData) {
           if (aTopic == "console-api-log-event") {
             var obj = aSubject.wrappedJSObject;
             if (obj.arguments[0] == "Hello from the debugger script!" &&
                 !consoleMessagesReceived) {
               consoleMessagesReceived++;
               ok(true, "Something has been received");
-              Services.obs.removeObserver(this, "console-api-log-event");
+              SpecialPowers.removeObserver(this, "console-api-log-event");
             }
           }
         }
       }
 
       var cl = new consoleListener();
 
       (async function() {
--- a/image/test/mochitest/test_bug671906.html
+++ b/image/test/mochitest/test_bug671906.html
@@ -19,40 +19,40 @@ https://bugzilla.mozilla.org/show_bug.cg
 var first, second, third;
 var correct, val1, val2;
 
 SimpleTest.waitForExplicitFinish();
 
 async function snapshotFirst()
 {
   var iframeelem = document.getElementById('test-iframe');
-  first = await SpecialPowers.wrap(snapshotWindow(iframeelem, false));
+  first = await snapshotWindow(iframeelem, false);
 
   iframeelem.onload = snapshotSecond;
   iframeelem.src = "http://example.com/tests/image/test/mochitest/bug671906-iframe.html";
 }
 
 async function snapshotSecond()
 {
   var iframeelem = document.getElementById('test-iframe');
-  second = await SpecialPowers.wrap(snapshotWindow(iframeelem, false));
+  second = await snapshotWindow(iframeelem, false);
 
   // We must have loaded the image again, because the principals for the
   // loading document are different.
   [correct, val1, val2] = compareSnapshots(first, second, false);
   ok(correct, "Image should have changed after changing the iframe's src.");
 
   iframeelem.onload = snapshotThird;
   iframeelem.src = "http://mochi.test:8888/tests/image/test/mochitest/bug671906-iframe.html";
 }
 
 async function snapshotThird()
 {
   var iframeelem = document.getElementById('test-iframe');
-  third = await SpecialPowers.wrap(snapshotWindow(iframeelem, false));
+  third = await snapshotWindow(iframeelem, false);
 
   // We must have loaded the image again, because the principals for the
   // loading document are different.
   [correct, val1, val2] = compareSnapshots(second, third, false);
   ok(correct, "Image should have changed after changing the iframe's src.");
 
   // We must have looped back to the first image, because the sjs only sends
   // one of two images.
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -613,16 +613,24 @@ bool mozJSComponentLoader::ReuseGlobal(n
   }
 
   // Various tests call addDebuggerToGlobal on the result of
   // importing this JSM, which would be annoying to fix.
   if (spec.EqualsASCII("resource://gre/modules/jsdebugger.jsm")) {
     return false;
   }
 
+  // Some SpecialPowers jsms call Cu.forcePermissiveCOWs(),
+  // which sets a per-compartment flag that disables certain
+  // security wrappers, so don't use the shared global for them
+  // to avoid breaking tests.
+  if (FindInReadable(NS_LITERAL_CSTRING("resource://specialpowers/"), spec)) {
+    return false;
+  }
+
   return true;
 }
 
 JSObject* mozJSComponentLoader::GetSharedGlobal(JSContext* aCx) {
   if (!mLoaderGlobal) {
     JS::RootedObject globalObj(aCx);
     CreateLoaderGlobal(aCx, NS_LITERAL_CSTRING("shared JSM global"),
                        &globalObj);
--- a/js/xpconnect/tests/mochitest/chrome_wrappers_helper.html
+++ b/js/xpconnect/tests/mochitest/chrome_wrappers_helper.html
@@ -1,25 +1,24 @@
 <html>
     <head>
         <script>
             function check_wrapper(ok, wrapper, expected, note) {
-                let { getClassName } = SpecialPowers.unwrap(
-                  SpecialPowers.wrap(window).ChromeUtils
-                );
-                ok(getClassName(wrapper, false) === expected, note);
+
+                var utils = SpecialPowers.DOMWindowUtils;
+                ok(utils.getClassName(wrapper) === expected, note);
             }
             function run_test(ok, xpcnw, sjow) {
                 // both wrappers should point to our window: XOW
-                check_wrapper(ok, ok, "Proxy", "functions are wrapped properly");
+                check_wrapper(ok, ok, "Proxy", "functions are wrapped properly")
                 check_wrapper(ok, xpcnw, "Proxy", "XPCNWs are transformed correctly");
                 check_wrapper(ok, sjow, "Proxy", "SJOWs are transformed correctly");
 
-                check_wrapper(ok, window.location, "Location",
-                              "same-compartment security wrappers are gone");
+                check_wrapper(ok, window.location, "Proxy",
+                              "Content needs a same-compartment security wrappers around location");
 
                 ok(defprop1 === 1, "defprop1 exists");
                 window.defprop1 = 2;
                 ok(defprop1 === 2, "defprop1 is properly writable");
 
                 // defprop2 = {}; disabled because the test doesn't work
             }
         </script>
--- a/layout/base/tests/test_bug416896.html
+++ b/layout/base/tests/test_bug416896.html
@@ -33,25 +33,25 @@ https://bugzilla.mozilla.org/show_bug.cg
 
  var inspectedRules = InspectorUtils.getCSSStyleRules(document.links[0]);
 
  var seenInline = false;
  var seenLinked = false;
  
  for (var i = 0; i < inspectedRules.length; ++i)
  {
-   var rule = inspectedRules[i];
+   var rule = SpecialPowers.unwrap(inspectedRules[i]);
    var sheet = rule.parentStyleSheet;
-   if (SpecialPowers.unwrap(sheet) == inlineSheet) {
+   if (sheet == inlineSheet) {
      is(sheet.href, null, "It's an inline sheet");
      is(seenInline, false, "Only one inline rule matches");
      seenInline = true;
    } else {
      isnot(sheet.href, null, "Shouldn't have null href here " + i);
-     if (SpecialPowers.unwrap(sheet) == linkedSheet) {
+     if (sheet == linkedSheet) {
        is(seenLinked, false, "Only one linked rule matches");
        seenLinked = true;
      }
    }
  }
 
  is(seenLinked, true, "Didn't find the linked rule?");
  is(seenInline, true, "Didn't find the inline rule?");
--- a/layout/inspector/tests/test_getCSSStyleRules.html
+++ b/layout/inspector/tests/test_getCSSStyleRules.html
@@ -19,17 +19,17 @@ const InspectorUtils = SpecialPowers.Ins
 
 let iframe = document.getElementById("test");
 
 SimpleTest.waitForExplicitFinish();
 
 function* getStyleRules(elem) {
   let rules = InspectorUtils.getCSSStyleRules(elem);
   for (let i = 0; i < rules.length; i++) {
-    yield rules[i];
+    yield SpecialPowers.unwrap(rules[i]);
   }
 }
 
 // This will check that value of z-index property declarations in the
 // rules from getCSSStyleRules matches the given content.
 function checkRules(doc, rulesContent, queryStr = "unknowntagname") {
   let elem = doc.querySelector(queryStr);
   let rules = [...getStyleRules(elem)];
--- a/layout/style/test/test_restyles_in_smil_animation.html
+++ b/layout/style/test/test_restyles_in_smil_animation.html
@@ -65,17 +65,17 @@ function observeStyling(frameCount) {
 
   docShell.recordProfileTimelineMarkers = true;
   docShell.popProfileTimelineMarkers();
 
   return new Promise(function(resolve) {
     return waitForAnimationFrames(frameCount).then(framesWaited => {
       var markers = docShell.popProfileTimelineMarkers();
       docShell.recordProfileTimelineMarkers = false;
-      var stylingMarkers = Array.prototype.filter.call(markers, function(marker, index) {
+      var stylingMarkers = markers.filter(function(marker, index) {
         return marker.name == 'Styles' && marker.isAnimationOnly;
       });
       resolve({
         stylingCount: stylingMarkers.length,
         framesWaited: framesWaited,
       });
     });
   });
--- a/testing/mochitest/tests/SimpleTest/MockObjects.js
+++ b/testing/mochitest/tests/SimpleTest/MockObjects.js
@@ -40,21 +40,23 @@ MockObjectRegisterer.prototype = {
     // Define a factory that creates a new object using the given constructor.
     var isChrome = location.protocol == "chrome:";
     var providedConstructor = this._replacementCtor;
     this._mockFactory = {
       createInstance: function MF_createInstance(aOuter, aIid) {
         if (aOuter != null) {
           throw SpecialPowers.Cr.NS_ERROR_NO_AGGREGATION;
         }
-        var inst = new providedConstructor().QueryInterface(aIid);
+        var inst = new providedConstructor();
         if (!isChrome) {
+          var QI = inst.QueryInterface;
           inst = SpecialPowers.wrapCallbackObject(inst);
+          inst.QueryInterface = QI;
         }
-        return inst;
+        return inst.QueryInterface(aIid);
       },
     };
     if (!isChrome) {
       this._mockFactory = SpecialPowers.wrapCallbackObject(this._mockFactory);
     }
 
     var retVal = SpecialPowers.swapFactoryRegistration(
       null,
--- a/testing/mochitest/tests/SimpleTest/SimpleTest.js
+++ b/testing/mochitest/tests/SimpleTest/SimpleTest.js
@@ -960,21 +960,17 @@ SimpleTest.waitForFocus = function(callb
       } else {
         childDesiredWindow = SpecialPowers.getFocusedElementForWindow(
           desiredWindow,
           true
         );
       }
 
       /* If this is a child frame, ensure that the frame is focused. */
-      if (isChildProcess) {
-        focused = focusedWindow() == childDesiredWindow;
-      } else {
-        focused = SpecialPowers.compare(focusedWindow(), childDesiredWindow);
-      }
+      focused = focusedWindow() == childDesiredWindow;
       if (!focused) {
         info("must wait for focus");
         childDesiredWindow.addEventListener("focus", focusedOrLoaded, true);
         if (isChildProcess) {
           childDesiredWindow.focus();
         } else {
           SpecialPowers.focus(childDesiredWindow);
         }
--- a/testing/specialpowers/content/MockColorPicker.jsm
+++ b/testing/specialpowers/content/MockColorPicker.jsm
@@ -1,25 +1,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 var EXPORTED_SYMBOLS = ["MockColorPicker"];
 
-ChromeUtils.defineModuleGetter(
-  this,
-  "WrapPrivileged",
-  "resource://specialpowers/WrapPrivileged.jsm"
-);
-
 const Cm = Components.manager;
 
 const CONTRACT_ID = "@mozilla.org/colorpicker;1";
 
-Cu.crashIfNotInAutomation();
+// Allow stuff from this scope to be accessed from non-privileged scopes. This
+// would crash if used outside of automation.
+Cu.forcePermissiveCOWs();
 
 var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
 var oldClassID = "";
 var newClassID = Cc["@mozilla.org/uuid-generator;1"]
   .getService(Ci.nsIUUIDGenerator)
   .generateUUID();
 var newFactory = function(window) {
   return {
@@ -70,18 +66,16 @@ var MockColorPicker = {
     if (oldClassID != "") {
       registrar.registerFactory(oldClassID, "", CONTRACT_ID, null);
     }
   },
 };
 
 function MockColorPickerInstance(window) {
   this.window = window;
-  this.showCallback = null;
-  this.showCallbackWrapped = null;
 }
 MockColorPickerInstance.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIColorPicker]),
   init(aParent, aTitle, aInitialColor) {
     this.parent = aParent;
     this.initialColor = aInitialColor;
   },
   initialColor: "",
@@ -89,32 +83,21 @@ MockColorPickerInstance.prototype = {
   open(aColorPickerShownCallback) {
     MockColorPicker.showing = true;
     MockColorPicker.shown = true;
 
     this.window.setTimeout(() => {
       let result = "";
       try {
         if (typeof MockColorPicker.showCallback == "function") {
-          if (MockColorPicker.showCallback != this.showCallback) {
-            this.showCallback = MockColorPicker.showCallback;
-            if (Cu.isXrayWrapper(this.window)) {
-              this.showCallbackWrapped = WrapPrivileged.wrapCallback(
-                MockColorPicker.showCallback,
-                this.window
-              );
-            } else {
-              this.showCallbackWrapped = this.showCallback;
-            }
-          }
           var updateCb = function(color) {
             result = color;
             aColorPickerShownCallback.update(color);
           };
-          let returnColor = this.showCallbackWrapped(this, updateCb);
+          let returnColor = MockColorPicker.showCallback(this, updateCb);
           if (typeof returnColor === "string") {
             result = returnColor;
           }
         } else if (typeof MockColorPicker.returnColor === "string") {
           result = MockColorPicker.returnColor;
         }
       } catch (ex) {
         dump(
--- a/testing/specialpowers/content/MockFilePicker.jsm
+++ b/testing/specialpowers/content/MockFilePicker.jsm
@@ -1,34 +1,30 @@
 /* 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/. */
 
 var EXPORTED_SYMBOLS = ["MockFilePicker"];
 
-ChromeUtils.defineModuleGetter(
-  this,
-  "WrapPrivileged",
-  "resource://specialpowers/WrapPrivileged.jsm"
-);
-
 const Cm = Components.manager;
 
 const CONTRACT_ID = "@mozilla.org/filepicker;1";
 
 ChromeUtils.defineModuleGetter(
   this,
   "FileUtils",
   "resource://gre/modules/FileUtils.jsm"
 );
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
+// Allow stuff from this scope to be accessed from non-privileged scopes. This
+// would crash if used outside of automation.
 /* globals __URI__ */
 if (__URI__.includes("specialpowers")) {
-  Cu.crashIfNotInAutomation();
+  Cu.forcePermissiveCOWs();
 }
 
 var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
 var oldClassID;
 var newClassID = Cc["@mozilla.org/uuid-generator;1"]
   .getService(Ci.nsIUUIDGenerator)
   .generateUUID();
 var newFactory = function(window) {
@@ -172,18 +168,16 @@ var MockFilePicker = {
       return this.returnData[0].nsIFile;
     }
     return null;
   },
 };
 
 function MockFilePickerInstance(window) {
   this.window = window;
-  this.showCallback = null;
-  this.showCallbackWrapped = null;
 }
 MockFilePickerInstance.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIFilePicker]),
   init(aParent, aTitle, aMode) {
     MockFilePicker.mode = aMode;
     this.filterIndex = MockFilePicker.filterIndex;
     this.parent = aParent;
   },
@@ -274,29 +268,18 @@ MockFilePickerInstance.prototype = {
           if (result == Ci.nsIFilePicker.returnCancel) {
             return result;
           }
 
           MockFilePicker.displayDirectory = this.displayDirectory;
           MockFilePicker.displaySpecialDirectory = this.displaySpecialDirectory;
           MockFilePicker.shown = true;
           if (typeof MockFilePicker.showCallback == "function") {
-            if (MockFilePicker.showCallback != this.showCallback) {
-              this.showCallback = MockFilePicker.showCallback;
-              if (Cu.isXrayWrapper(this.window)) {
-                this.showCallbackWrapped = WrapPrivileged.wrapCallback(
-                  MockFilePicker.showCallback,
-                  this.window
-                );
-              } else {
-                this.showCallbackWrapped = this.showCallback;
-              }
-            }
             try {
-              var returnValue = this.showCallbackWrapped(this);
+              var returnValue = MockFilePicker.showCallback(this);
               if (typeof returnValue != "undefined") {
                 return returnValue;
               }
             } catch (ex) {
               return Ci.nsIFilePicker.returnCancel;
             }
           }
 
--- a/testing/specialpowers/content/SpecialPowersChild.jsm
+++ b/testing/specialpowers/content/SpecialPowersChild.jsm
@@ -60,29 +60,30 @@ ChromeUtils.defineModuleGetter(
   "resource://testing-common/PerTestCoverageUtils.jsm"
 );
 ChromeUtils.defineModuleGetter(
   this,
   "ContentTaskUtils",
   "resource://testing-common/ContentTaskUtils.jsm"
 );
 
-Cu.crashIfNotInAutomation();
+// Allow stuff from this scope to be accessed from non-privileged scopes. This
+// would crash if used outside of automation.
+Cu.forcePermissiveCOWs();
 
 function bindDOMWindowUtils(aWindow) {
-  return aWindow && WrapPrivileged.wrap(aWindow.windowUtils, aWindow);
+  return aWindow && WrapPrivileged.wrap(aWindow.windowUtils);
 }
 
 // SPConsoleListener reflects nsIConsoleMessage objects into JS in a
 // tidy, XPCOM-hiding way.  Messages that are nsIScriptError objects
 // have their properties exposed in detail.  It also auto-unregisters
 // itself when it receives a "sentinel" message.
-function SPConsoleListener(callback, contentWindow) {
+function SPConsoleListener(callback) {
   this.callback = callback;
-  this.contentWindow = contentWindow;
 }
 
 SPConsoleListener.prototype = {
   // Overload the observe method for both nsIConsoleListener and nsIObserver.
   // The topic will be null for nsIConsoleListener.
   observe(msg, topic) {
     let m = {
       message: msg.message,
@@ -123,17 +124,17 @@ SPConsoleListener.prototype = {
       m.isWarning = unwrapped.level === "warning";
     }
 
     Object.freeze(m);
 
     // Run in a separate runnable since console listeners aren't
     // supposed to touch content and this one might.
     Services.tm.dispatchToMainThread(() => {
-      this.callback.call(undefined, Cu.cloneInto(m, this.contentWindow));
+      this.callback.call(undefined, m);
     });
 
     if (!m.isScriptError && !m.isConsoleEvent && m.message === "SENTINEL") {
       Services.obs.removeObserver(this, "console-api-log-event");
       Services.console.unregisterListener(this);
     }
   },
 
@@ -143,26 +144,27 @@ SPConsoleListener.prototype = {
   ]),
 };
 
 class SpecialPowersChild extends JSWindowActorChild {
   constructor() {
     super();
 
     this._windowID = null;
+    this.DOMWindowUtils = null;
 
     this._encounteredCrashDumpFiles = [];
     this._unexpectedCrashDumpFiles = {};
     this._crashDumpDir = null;
     this._serviceWorkerRegistered = false;
     this._serviceWorkerCleanUpRequests = new Map();
     Object.defineProperty(this, "Components", {
       configurable: true,
       enumerable: true,
-      value: Components,
+      value: this.getFullComponents(),
     });
     this._createFilesOnError = null;
     this._createFilesOnSuccess = null;
 
     this._messageListeners = new ExtensionUtils.DefaultMap(() => new Set());
 
     this._consoleListeners = [];
     this._spawnTaskImports = {};
@@ -174,52 +176,35 @@ class SpecialPowersChild extends JSWindo
     this._observingPermissions = false;
     this._asyncObservers = new WeakMap();
     this._xpcomabi = null;
     this._os = null;
     this._pu = null;
 
     this._nextExtensionID = 0;
     this._extensionListeners = null;
-
-    WrapPrivileged.disableAutoWrap(
-      this.unwrap,
-      this.isWrapper,
-      this.wrapCallback,
-      this.wrapCallbackObject,
-      this.setWrapped,
-      this.nondeterministicGetWeakMapKeys,
-      this.snapshotWindowWithOptions,
-      this.snapshotWindow,
-      this.snapshotRect,
-      this.getDOMRequestService
-    );
   }
 
   observe(aSubject, aTopic, aData) {
     // Ignore the "{chrome/content}-document-global-created" event. It
     // is only observed to force creation of the actor.
   }
 
   actorCreated() {
     this.attachToWindow();
   }
 
   attachToWindow() {
     let window = this.contentWindow;
     if (!window.wrappedJSObject.SpecialPowers) {
       this._windowID = window.windowUtils.currentInnerWindowID;
+      this.DOMWindowUtils = bindDOMWindowUtils(window);
 
       window.SpecialPowers = this;
-      if (window !== window.wrappedJSObject) {
-        window.wrappedJSObject.SpecialPowers = WrapPrivileged.wrap(
-          this,
-          window
-        );
-      }
+      window.wrappedJSObject.SpecialPowers = this;
       if (this.IsInNestedFrame) {
         this.addPermission("allowXULXBL", true, window.document);
       }
     }
   }
 
   get window() {
     return this.contentWindow;
@@ -353,44 +338,37 @@ class SpecialPowersChild extends JSWindo
    *  - The wrapper cannot see expando properties on unprivileged DOM objects.
    *    That is to say, the wrapper uses Xray delegation.
    *
    *  - The wrapper sometimes guesses certain ES5 attributes for returned
    *    properties. This is explained in a comment in the wrapper code above,
    *    and shouldn't be a problem.
    */
   wrap(obj) {
-    return obj;
+    return WrapPrivileged.wrap(obj);
   }
   unwrap(obj) {
     return WrapPrivileged.unwrap(obj);
   }
   isWrapper(val) {
     return WrapPrivileged.isWrapper(val);
   }
 
   /*
-   * Wrap objects on a specified global.
-   */
-  wrapFor(obj, win) {
-    return WrapPrivileged.wrap(obj, win);
-  }
-
-  /*
    * When content needs to pass a callback or a callback object to an API
    * accessed over SpecialPowers, that API may sometimes receive arguments for
    * whom it is forbidden to create a wrapper in content scopes. As such, we
    * need a layer to wrap the values in SpecialPowers wrappers before they ever
    * reach content.
    */
   wrapCallback(func) {
-    return WrapPrivileged.wrapCallback(func, this.contentWindow);
+    return WrapPrivileged.wrapCallback(func);
   }
   wrapCallbackObject(obj) {
-    return WrapPrivileged.wrapCallbackObject(obj, this.contentWindow);
+    return WrapPrivileged.wrapCallbackObject(obj);
   }
 
   /*
    * Used for assigning a property to a SpecialPowers wrapper, without unwrapping
    * the value that is assigned.
    */
   setWrapped(obj, prop, val) {
     if (!WrapPrivileged.isWrapper(obj)) {
@@ -438,17 +416,17 @@ class SpecialPowersChild extends JSWindo
   }
 
   // fileRequests is an array of file requests. Each file request is an object.
   // A request must have a field |name|, which gives the base of the name of the
   // file to be created in the profile directory. If the request has a |data| field
   // then that data will be written to the file.
   createFiles(fileRequests, onCreation, onError) {
     return this.sendQuery("SpecialPowers.CreateFiles", fileRequests).then(
-      files => onCreation(Cu.cloneInto(files, this.contentWindow)),
+      onCreation,
       onError
     );
   }
 
   // Remove the files that were created using |SpecialPowers.createFiles()|.
   // This will be automatically called by |SimpleTest.finish()|.
   removeFiles() {
     this.sendAsyncMessage("SpecialPowers.RemoveFiles", {});
@@ -502,19 +480,23 @@ class SpecialPowersChild extends JSWindo
    */
   loadPrivilegedScript(aFunction) {
     var str = "(" + aFunction.toString() + ")();";
     let gGlobalObject = Cu.getGlobalForObject(this);
     let sb = Cu.Sandbox(gGlobalObject);
     var window = this.contentWindow;
     var mc = new window.MessageChannel();
     sb.port = mc.port1;
-    let blob = new Blob([str], { type: "application/javascript" });
-    let blobUrl = URL.createObjectURL(blob);
-    Services.scriptloader.loadSubScript(blobUrl, sb);
+    try {
+      let blob = new Blob([str], { type: "application/javascript" });
+      let blobUrl = URL.createObjectURL(blob);
+      Services.scriptloader.loadSubScript(blobUrl, sb);
+    } catch (e) {
+      throw WrapPrivileged.wrap(e);
+    }
 
     return mc.port2;
   }
 
   _readUrlAsString(aUrl) {
     // Fetch script content as we can't use scriptloader's loadSubScript
     // to evaluate http:// urls...
     var scriptableStream = Cc[
@@ -638,87 +620,90 @@ class SpecialPowersChild extends JSWindo
             result = listener.listener(message);
           }
         }
         return result;
       },
     };
     this._addMessageListener("SPChromeScriptMessage", chromeScript);
 
-    return chromeScript;
+    return this.wrap(chromeScript);
   }
 
   async importInMainProcess(importString) {
     var message = await this.sendQuery("SPImportInMainProcess", importString);
     if (message.hadError) {
       throw new Error(
         "SpecialPowers.importInMainProcess failed with error " +
           message.errorMessage
       );
     }
   }
 
   get Services() {
-    return Services;
+    return WrapPrivileged.wrap(Services);
+  }
+
+  /*
+   * A getter for the privileged Components object we have.
+   */
+  getFullComponents() {
+    return Components;
   }
 
   /*
    * Convenient shortcuts to the standard Components abbreviations.
    */
   get Cc() {
-    return Cc;
+    return WrapPrivileged.wrap(this.getFullComponents().classes);
   }
   get Ci() {
-    return Ci;
+    return WrapPrivileged.wrap(this.getFullComponents().interfaces);
   }
   get Cu() {
-    return Cu;
+    return WrapPrivileged.wrap(this.getFullComponents().utils);
   }
   get Cr() {
-    return Cr;
+    return WrapPrivileged.wrap(this.getFullComponents().results);
   }
 
   get addProfilerMarker() {
     return ChromeUtils.addProfilerMarker;
   }
 
-  get DOMWindowUtils() {
-    return this.contentWindow.windowUtils;
-  }
-
   getDOMWindowUtils(aWindow) {
-    if (aWindow == this.contentWindow) {
-      return aWindow.windowUtils;
+    if (aWindow == this.contentWindow && this.DOMWindowUtils != null) {
+      return this.DOMWindowUtils;
     }
 
-    return bindDOMWindowUtils(Cu.unwaiveXrays(aWindow));
+    return bindDOMWindowUtils(aWindow);
   }
 
   async toggleMuteState(aMuted, aWindow) {
     let actor = aWindow
       ? aWindow.windowGlobalChild.getActor("SpecialPowers")
       : this;
     return actor.sendQuery("SPToggleMuteAudio", { mute: aMuted });
   }
 
   /*
    * A method to get a DOMParser that can't parse XUL.
    */
   getNoXULDOMParser() {
     // If we create it with a system subject principal (so it gets a
     // nullprincipal), it won't be able to parse XUL by default.
-    return new DOMParser();
+    return WrapPrivileged.wrap(new DOMParser());
   }
 
   get InspectorUtils() {
-    return InspectorUtils;
+    return WrapPrivileged.wrap(InspectorUtils);
   }
 
   get PromiseDebugging() {
-    return PromiseDebugging;
+    return WrapPrivileged.wrap(PromiseDebugging);
   }
 
   async waitForCrashes(aExpectingProcessCrash) {
     if (!aExpectingProcessCrash) {
       return;
     }
 
     var crashIds = this._encounteredCrashDumpFiles
@@ -812,17 +797,17 @@ class SpecialPowersChild extends JSWindo
   async pushPermissions(inPermissions, callback) {
     inPermissions = Cu.waiveXrays(inPermissions);
     var pendingPermissions = [];
     var cleanupPermissions = [];
 
     for (var p in inPermissions) {
       var permission = inPermissions[p];
       var originalValue = Ci.nsIPermissionManager.UNKNOWN_ACTION;
-      var context = WrapPrivileged.unwrap(Cu.unwaiveXrays(permission.context)); // Sometimes |context| is a DOM object on which we expect
+      var context = Cu.unwaiveXrays(permission.context); // Sometimes |context| is a DOM object on which we expect
       // to be able to access .nodePrincipal, so we need to unwaive.
       if (
         await this.testPermission(
           permission.type,
           Ci.nsIPermissionManager.ALLOW_ACTION,
           context
         )
       ) {
@@ -1087,20 +1072,17 @@ class SpecialPowersChild extends JSWindo
     this.sendAsyncMessage("Wakeup");
 
     this._addObserverProxy(notification);
     obs = Cu.waiveXrays(obs);
     if (
       typeof obs == "object" &&
       obs.observe.name != "SpecialPowersCallbackWrapper"
     ) {
-      obs.observe = WrapPrivileged.wrapCallback(
-        Cu.unwaiveXrays(obs.observe),
-        this.contentWindow
-      );
+      obs.observe = WrapPrivileged.wrapCallback(obs.observe);
     }
     Services.obs.addObserver(obs, notification, weak);
   }
   removeObserver(obs, notification) {
     this._removeObserverProxy(notification);
     Services.obs.removeObserver(Cu.waiveXrays(obs), notification);
   }
   notifyObservers(subject, topic, data) {
@@ -1117,20 +1099,17 @@ class SpecialPowersChild extends JSWindo
    * avoids this problem.
    */
   addAsyncObserver(obs, notification, weak) {
     obs = Cu.waiveXrays(obs);
     if (
       typeof obs == "object" &&
       obs.observe.name != "SpecialPowersCallbackWrapper"
     ) {
-      obs.observe = WrapPrivileged.wrapCallback(
-        Cu.unwaiveXrays(obs.observe),
-        this.contentWindow
-      );
+      obs.observe = WrapPrivileged.wrapCallback(obs.observe);
     }
     let asyncObs = (...args) => {
       Services.tm.dispatchToMainThread(() => {
         if (typeof obs == "function") {
           obs(...args);
         } else {
           obs.observe.call(undefined, ...args);
         }
@@ -1270,17 +1249,17 @@ class SpecialPowersChild extends JSWindo
     this._getAutoCompletePopup(window).addEventListener(eventname, listener);
   }
   removeAutoCompletePopupEventListener(window, eventname, listener) {
     this._getAutoCompletePopup(window).removeEventListener(eventname, listener);
   }
   get formHistory() {
     let tmp = {};
     ChromeUtils.import("resource://gre/modules/FormHistory.jsm", tmp);
-    return tmp.FormHistory;
+    return WrapPrivileged.wrap(tmp.FormHistory);
   }
   getFormFillController(window) {
     return Cc["@mozilla.org/satchel/form-fill-controller;1"].getService(
       Ci.nsIFormFillController
     );
   }
   attachFormFillControllerTo(window) {
     this.getFormFillController().attachPopupElementToDocument(
@@ -1320,17 +1299,17 @@ class SpecialPowersChild extends JSWindo
 
   // Note: each call to registerConsoleListener MUST be paired with a
   // call to postConsoleSentinel; when the callback receives the
   // sentinel it will unregister itself (_after_ calling the
   // callback).  SimpleTest.expectConsoleMessages does this for you.
   // If you register more than one console listener, a call to
   // postConsoleSentinel will zap all of them.
   registerConsoleListener(callback) {
-    let listener = new SPConsoleListener(callback, this.contentWindow);
+    let listener = new SPConsoleListener(callback);
     Services.console.registerListener(listener);
 
     // listen for dom/console events as well
     Services.obs.addObserver(listener, "console-api-log-event");
   }
   postConsoleSentinel() {
     Services.console.logStringMessage("SENTINEL");
   }
@@ -1460,17 +1439,17 @@ class SpecialPowersChild extends JSWindo
     });
   }
 
   snapshotRect(win, rect, bgcolor) {
     return this.snapshotWindowWithOptions(win, rect, bgcolor);
   }
 
   gc() {
-    this.contentWindow.windowUtils.garbageCollect();
+    this.DOMWindowUtils.garbageCollect();
   }
 
   forceGC() {
     Cu.forceGC();
   }
 
   forceShrinkingGC() {
     Cu.forceShrinkingGC();
@@ -1506,21 +1485,17 @@ class SpecialPowersChild extends JSWindo
         }
       };
     }
 
     Cu.schedulePreciseGC(genGCCallback(callback));
   }
 
   nondeterministicGetWeakMapKeys(m) {
-    let keys = ChromeUtils.nondeterministicGetWeakMapKeys(m);
-    if (!keys) {
-      return undefined;
-    }
-    return this.contentWindow.Array.from(keys);
+    return ChromeUtils.nondeterministicGetWeakMapKeys(m);
   }
 
   getMemoryReports() {
     try {
       Cc["@mozilla.org/memory-reporter-manager;1"]
         .getService(Ci.nsIMemoryReporterManager)
         .getReports(
           () => {},
@@ -1609,17 +1584,17 @@ class SpecialPowersChild extends JSWindo
       "fireDetailedError",
     ];
     for (var i in props) {
       let prop = props[i];
       res[prop] = function() {
         return serv[prop].apply(serv, arguments);
       };
     }
-    return Cu.cloneInto(res, this.contentWindow, { cloneFunctions: true });
+    return res;
   }
 
   addCategoryEntry(category, entry, value, persists, replace) {
     Services.catMan.addCategoryEntry(category, entry, value, persists, replace);
   }
 
   deleteCategoryEntry(category, entry, persists) {
     Services.catMan.deleteCategoryEntry(category, entry, persists);
@@ -2138,17 +2113,19 @@ class SpecialPowersChild extends JSWindo
   }
 
   allowMedia(window, enable) {
     window.docShell.allowMedia = enable;
   }
 
   createChromeCache(name, url) {
     let principal = this._getPrincipalFromArg(url);
-    return new this.contentWindow.CacheStorage(name, principal);
+    return WrapPrivileged.wrap(
+      new this.contentWindow.CacheStorage(name, principal)
+    );
   }
 
   loadChannelAndReturnStatus(url, loadUsingSystemPrincipal) {
     const BinaryInputStream = Components.Constructor(
       "@mozilla.org/binaryinputstream;1",
       "nsIBinaryInputStream",
       "setInputStream"
     );
@@ -2215,23 +2192,22 @@ class SpecialPowersChild extends JSWindo
   createDOMWalker(node, showAnonymousContent) {
     node = WrapPrivileged.unwrap(node);
     let walker = Cc["@mozilla.org/inspector/deep-tree-walker;1"].createInstance(
       Ci.inIDeepTreeWalker
     );
     walker.showAnonymousContent = showAnonymousContent;
     walker.init(node.ownerDocument, NodeFilter.SHOW_ALL);
     walker.currentNode = node;
-    let contentWindow = this.contentWindow;
     return {
       get firstChild() {
-        return WrapPrivileged.wrap(walker.firstChild(), contentWindow);
+        return WrapPrivileged.wrap(walker.firstChild());
       },
       get lastChild() {
-        return WrapPrivileged.wrap(walker.lastChild(), contentWindow);
+        return WrapPrivileged.wrap(walker.lastChild());
       },
     };
   }
 
   observeMutationEvents(mo, node, nativeAnonymousChildList, subtree) {
     WrapPrivileged.unwrap(mo).observe(WrapPrivileged.unwrap(node), {
       nativeAnonymousChildList,
       subtree,
@@ -2300,21 +2276,21 @@ class SpecialPowersChild extends JSWindo
   doUrlClassifyLocal(uri, tables, callback) {
     let classifierService = Cc[
       "@mozilla.org/url-classifier/dbservice;1"
     ].getService(Ci.nsIURIClassifier);
 
     let wrapCallback = results => {
       Services.tm.dispatchToMainThread(() => {
         if (typeof callback == "function") {
-          callback(WrapPrivileged.wrap(results, this.contentWindow));
+          callback(WrapPrivileged.wrap(results));
         } else {
           callback.onClassifyComplete.call(
             undefined,
-            WrapPrivileged.wrap(results, this.contentWindow)
+            WrapPrivileged.wrap(results)
           );
         }
       });
     };
 
     let feature = classifierService.createFeatureWithTables(
       "test",
       tables.split(","),
--- a/testing/specialpowers/content/WrapPrivileged.jsm
+++ b/testing/specialpowers/content/WrapPrivileged.jsm
@@ -10,49 +10,57 @@
  * Its exact semantics are also liable to change at any time, so any callers
  * relying on undocumented behavior or subtle platform features should expect
  * breakage. Those callers should, wherever possible, migrate to fully
  * chrome-privileged scripts when they need to interact with privileged APIs.
  */
 
 /* globals XPCNativeWrapper */
 
-Cu.crashIfNotInAutomation();
+if (!Cu.isInAutomation) {
+  throw new Error("WrapPrivileged.jsm is only for use in automation");
+}
+
+// This code currently works by creating Proxy objects in a privileged
+// compartment and exposing them directly to content scopes. Enabling
+// permissive COWs for this compartment allows the unprivileged compartment to
+// access them.
+//
+// In the future, we want to remove support for permissive COWs, which will
+// mean creating the proxy objects in the unprivileged caller's scope instead.
+Cu.forcePermissiveCOWs();
 
 var EXPORTED_SYMBOLS = ["WrapPrivileged"];
 
-let wrappedObjects = new WeakMap();
-let contentWindows = new WeakMap();
-let perWindowInfo = new WeakMap();
-let noAutoWrap = new WeakSet();
-
 function isWrappable(x) {
   if (typeof x === "object") {
     return x !== null;
   }
   return typeof x === "function";
 }
 
 function isWrapper(x) {
   try {
-    return isWrappable(x) && wrappedObjects.has(x);
+    return (
+      isWrappable(x) && typeof x.SpecialPowers_wrappedObject !== "undefined"
+    );
   } catch (e) {
     // If `x` is a remote object proxy, trying to access an unexpected property
     // on it will throw a security error, even though we're chrome privileged.
     // However, remote proxies are not SpecialPowers wrappers, so:
     return false;
   }
 }
 
 function unwrapIfWrapped(x) {
   return isWrapper(x) ? unwrapPrivileged(x) : x;
 }
 
-function wrapIfUnwrapped(x, w) {
-  return isWrapper(x) ? x : wrapPrivileged(x, w);
+function wrapIfUnwrapped(x) {
+  return isWrapper(x) ? x : wrapPrivileged(x);
 }
 
 function isObjectOrArray(obj) {
   if (Object(obj) !== obj) {
     return false;
   }
   let arrayClasses = [
     "Object",
@@ -96,20 +104,16 @@ function waiveXraysIfAppropriate(obj, pr
     isObjectOrArray(obj) ||
     /Opaque/.test(Object.prototype.toString.call(obj))
   ) {
     return XPCNativeWrapper.unwrap(obj);
   }
   return obj;
 }
 
-let tip = Cc["@mozilla.org/text-input-processor;1"].createInstance(
-  Ci.nsITextInputProcessor
-);
-
 // We can't call apply() directy on Xray-wrapped functions, so we have to be
 // clever.
 function doApply(fun, invocant, args) {
   // We implement Xrays to pure JS [[Object]] instances that filter out tricky
   // things like callables. This is the right thing for security in general,
   // but tends to break tests that try to pass object literals into
   // SpecialPowers. So we waive [[Object]] instances when they're passed to a
   // SpecialPowers-wrapped callable.
@@ -118,312 +122,245 @@ function doApply(fun, invocant, args) {
   // pulled off such an object will also be waived, and so we'll get principal
   // clamping for Xrayed DOM objects reached from literals, so passing things
   // like {l : xoWin.location} won't work. Hopefully the rabbit hole doesn't
   // go that deep.
   args = args.map(x => (isObjectOrArray(x) ? Cu.waiveXrays(x) : x));
   return Reflect.apply(fun, invocant, args);
 }
 
-function wrapPrivileged(obj, win) {
+function wrapPrivileged(obj) {
   // Primitives pass straight through.
   if (!isWrappable(obj)) {
     return obj;
   }
 
   // No double wrapping.
   if (isWrapper(obj)) {
     throw new Error("Trying to double-wrap object!");
   }
 
-  let { windowID, proxies, handler } = perWindowInfo.get(win) || {};
-  // |windowUtils| is undefined if |win| is a non-window object
-  // such as a sandbox.
-  let currentID = win.windowUtils ? win.windowUtils.currentInnerWindowID : 0;
-  // Values are dead objects if the inner window is changed.
-  if (windowID !== currentID) {
-    windowID = currentID;
-    proxies = new WeakMap();
-    handler = Cu.cloneInto(SpecialPowersHandler, win, {
-      cloneFunctions: true,
-    });
-    contentWindows.set(handler, win);
-    perWindowInfo.set(win, { windowID, proxies, handler });
-  }
-
-  if (proxies.has(obj)) {
-    return proxies.get(obj);
-  }
-
-  let className = Cu.getClassName(obj, true);
-  if (className === "ArrayBuffer") {
-    // Since |new Uint8Array(<proxy>)| doesn't work as expected, we have to
-    // return a real ArrayBuffer.
-    return obj instanceof win.ArrayBuffer ? obj : Cu.cloneInto(obj, win);
-  }
-
   let dummy;
   if (typeof obj === "function") {
-    dummy = Cu.exportFunction(function() {}, win);
+    dummy = function() {};
   } else {
-    dummy = new win.Object();
+    dummy = Object.create(null);
   }
 
-  wrappedObjects.set(dummy, obj);
-  let proxy = new win.Proxy(dummy, handler);
-  wrappedObjects.set(proxy, obj);
-  switch (className) {
-    case "AnonymousContent":
-      // Caching anonymous content will cause crashes (bug 1636015).
-      break;
-    case "CSS2Properties":
-    case "CSSStyleRule":
-    case "CSSStyleSheet":
-      // Caching these classes will cause memory leaks.
-      break;
-    case "Object":
-    case "Array":
-      // Caching Xray wrapped objects/arrays will cause crashes in debug builds.
-      if (Cu.unwaiveXrays(obj) === obj) {
-        proxies.set(obj, proxy);
-      }
-      break;
-    case "Function":
-      // Caching nsITextInputProcessor methods will cause crashes in debug builds.
-      if (!(obj.name in tip)) {
-        proxies.set(obj, proxy);
-      }
-      break;
-    default:
-      proxies.set(obj, proxy);
-      break;
-  }
-  return proxy;
+  return new Proxy(dummy, new SpecialPowersHandler(obj));
 }
 
 function unwrapPrivileged(x) {
   // We don't wrap primitives, so sometimes we have a primitive where we'd
   // expect to have a wrapper. The proxy pretends to be the type that it's
   // emulating, so we can just as easily check isWrappable() on a proxy as
   // we can on an unwrapped object.
   if (!isWrappable(x)) {
     return x;
   }
 
   // If we have a wrappable type, make sure it's wrapped.
   if (!isWrapper(x)) {
     throw new Error("Trying to unwrap a non-wrapped object!");
   }
 
+  var obj = x.SpecialPowers_wrappedObject;
   // unwrapped.
-  return wrappedObjects.get(x);
+  return obj;
 }
 
 function specialPowersHasInstance(value) {
   // Because we return wrapped versions of this function, when it's called its
   // wrapper will unwrap the "this" as well as the function itself.  So our
   // "this" is the unwrapped thing we started out with.
   return value instanceof this;
 }
 
-let SpecialPowersHandler = {
+function SpecialPowersHandler(wrappedObject) {
+  this.wrappedObject = wrappedObject;
+}
+
+SpecialPowersHandler.prototype = {
   construct(target, args) {
     // The arguments may or may not be wrappers. Unwrap them if necessary.
-    var unwrappedArgs = Array.from(Cu.waiveXrays(args), x =>
-      unwrapIfWrapped(Cu.unwaiveXrays(x))
-    );
+    var unwrappedArgs = Array.prototype.slice.call(args).map(unwrapIfWrapped);
 
     // We want to invoke "obj" as a constructor, but using unwrappedArgs as
     // the arguments.  Make sure to wrap and re-throw exceptions!
     try {
       return wrapIfUnwrapped(
-        Reflect.construct(wrappedObjects.get(target), unwrappedArgs),
-        contentWindows.get(this)
+        Reflect.construct(this.wrappedObject, unwrappedArgs)
       );
     } catch (e) {
-      throw wrapIfUnwrapped(e, contentWindows.get(this));
+      throw wrapIfUnwrapped(e);
     }
   },
 
   apply(target, thisValue, args) {
-    let wrappedObject = wrappedObjects.get(target);
-    let contentWindow = contentWindows.get(this);
     // The invocant and arguments may or may not be wrappers. Unwrap
     // them if necessary.
     var invocant = unwrapIfWrapped(thisValue);
-
-    if (noAutoWrap.has(wrappedObject)) {
-      args = Array.from(Cu.waiveXrays(args), x => Cu.unwaiveXrays(x));
-      try {
-        return doApply(wrappedObject, invocant, args);
-      } catch (e) {
-        // Wrap exceptions and re-throw them.
-        throw wrapIfUnwrapped(e, contentWindow);
-      }
-    }
-
-    if (wrappedObject.name == "then") {
-      args = Array.from(Cu.waiveXrays(args), x =>
-        wrapCallback(Cu.unwaiveXrays(x), contentWindow)
-      );
-    } else {
-      args = Array.from(Cu.waiveXrays(args), x =>
-        unwrapIfWrapped(Cu.unwaiveXrays(x))
-      );
-    }
+    var unwrappedArgs = Array.prototype.slice.call(args).map(unwrapIfWrapped);
 
     try {
       return wrapIfUnwrapped(
-        doApply(wrappedObject, invocant, args),
-        contentWindow
+        doApply(this.wrappedObject, invocant, unwrappedArgs)
       );
     } catch (e) {
       // Wrap exceptions and re-throw them.
-      throw wrapIfUnwrapped(e, contentWindow);
+      throw wrapIfUnwrapped(e);
     }
   },
 
   has(target, prop) {
-    return Reflect.has(wrappedObjects.get(target), prop);
+    if (prop === "SpecialPowers_wrappedObject") {
+      return true;
+    }
+
+    return Reflect.has(this.wrappedObject, prop);
   },
 
   get(target, prop, receiver) {
-    let obj = waiveXraysIfAppropriate(wrappedObjects.get(target), prop);
+    if (prop === "SpecialPowers_wrappedObject") {
+      return this.wrappedObject;
+    }
+
+    let obj = waiveXraysIfAppropriate(this.wrappedObject, prop);
     let val = Reflect.get(obj, prop);
     if (val === undefined && prop == Symbol.hasInstance) {
       // Special-case Symbol.hasInstance to pass the hasInstance check on to our
       // target.  We only do this when the target doesn't have its own
       // Symbol.hasInstance already.  Once we get rid of JS engine class
       // instance hooks (bug 1448218) and always use Symbol.hasInstance, we can
       // remove this bit (bug 1448400).
-      return wrapPrivileged(specialPowersHasInstance, contentWindows.get(this));
+      return wrapPrivileged(specialPowersHasInstance);
     }
-    return wrapIfUnwrapped(val, contentWindows.get(this));
+    return wrapIfUnwrapped(val);
   },
 
   set(target, prop, val, receiver) {
-    let obj = waiveXraysIfAppropriate(wrappedObjects.get(target), prop);
+    if (prop === "SpecialPowers_wrappedObject") {
+      return false;
+    }
+
+    let obj = waiveXraysIfAppropriate(this.wrappedObject, prop);
     return Reflect.set(obj, prop, unwrapIfWrapped(val));
   },
 
   delete(target, prop) {
-    return Reflect.deleteProperty(wrappedObjects.get(target), prop);
+    if (prop === "SpecialPowers_wrappedObject") {
+      return false;
+    }
+
+    return Reflect.deleteProperty(this.wrappedObject, prop);
   },
 
   defineProperty(target, prop, descriptor) {
     throw new Error(
       "Can't call defineProperty on SpecialPowers wrapped object"
     );
   },
 
   getOwnPropertyDescriptor(target, prop) {
-    let obj = waiveXraysIfAppropriate(wrappedObjects.get(target), prop);
+    // Handle our special API.
+    if (prop === "SpecialPowers_wrappedObject") {
+      return {
+        value: this.wrappedObject,
+        writeable: true,
+        configurable: true,
+        enumerable: false,
+      };
+    }
+
+    let obj = waiveXraysIfAppropriate(this.wrappedObject, prop);
     let desc = Reflect.getOwnPropertyDescriptor(obj, prop);
 
     if (desc === undefined) {
       if (prop == Symbol.hasInstance) {
         // Special-case Symbol.hasInstance to pass the hasInstance check on to
         // our target.  We only do this when the target doesn't have its own
         // Symbol.hasInstance already.  Once we get rid of JS engine class
         // instance hooks (bug 1448218) and always use Symbol.hasInstance, we
         // can remove this bit (bug 1448400).
         return {
-          value: wrapPrivileged(
-            specialPowersHasInstance,
-            contentWindows.get(this)
-          ),
+          value: wrapPrivileged(specialPowersHasInstance),
           writeable: true,
           configurable: true,
           enumerable: false,
         };
       }
 
       return undefined;
     }
 
     // Transitively maintain the wrapper membrane.
-    let wrapIfExists = key => {
+    function wrapIfExists(key) {
       if (key in desc) {
-        desc[key] = wrapIfUnwrapped(desc[key], contentWindows.get(this));
+        desc[key] = wrapIfUnwrapped(desc[key]);
       }
-    };
+    }
 
     wrapIfExists("value");
     wrapIfExists("get");
     wrapIfExists("set");
 
     // A trapping proxy's properties must always be configurable, but sometimes
     // we come across non-configurable properties. Tell a white lie.
     desc.configurable = true;
 
-    return wrapIfUnwrapped(desc, contentWindows.get(this));
+    return desc;
   },
 
   ownKeys(target) {
-    let props = [];
+    // Insert our special API. It's not enumerable, but ownKeys()
+    // includes non-enumerable properties.
+    let props = ["SpecialPowers_wrappedObject"];
 
     // Do the normal thing.
     let flt = a => !props.includes(a);
-    props = props.concat(
-      Reflect.ownKeys(wrappedObjects.get(target)).filter(flt)
-    );
+    props = props.concat(Reflect.ownKeys(this.wrappedObject).filter(flt));
 
     // If we've got an Xray wrapper, include the expandos as well.
-    if ("wrappedJSObject" in wrappedObjects.get(target)) {
+    if ("wrappedJSObject" in this.wrappedObject) {
       props = props.concat(
-        Reflect.ownKeys(wrappedObjects.get(target).wrappedJSObject).filter(flt)
+        Reflect.ownKeys(this.wrappedObject.wrappedJSObject).filter(flt)
       );
     }
 
-    return Cu.cloneInto(props, contentWindows.get(this));
+    return props;
   },
 
   preventExtensions(target) {
     throw new Error(
       "Can't call preventExtensions on SpecialPowers wrapped object"
     );
   },
 };
 
-function wrapCallback(cb, win) {
-  // Do not wrap if it is already privileged.
-  if (!isWrappable(cb) || Cu.getObjectPrincipal(cb).isSystemPrincipal) {
-    return cb;
-  }
+function wrapCallback(cb) {
   return function SpecialPowersCallbackWrapper() {
-    var args = Array.from(arguments, obj => wrapIfUnwrapped(obj, win));
-    let invocant = wrapIfUnwrapped(this, win);
-    return unwrapIfWrapped(cb.apply(invocant, args));
+    var args = Array.prototype.map.call(arguments, wrapIfUnwrapped);
+    return cb.apply(this, args);
   };
 }
 
-function wrapCallbackObject(obj, win) {
-  // Do not wrap if it is already privileged.
-  if (!isWrappable(obj) || Cu.getObjectPrincipal(obj).isSystemPrincipal) {
-    return obj;
-  }
+function wrapCallbackObject(obj) {
   obj = Cu.waiveXrays(obj);
   var wrapper = {};
   for (var i in obj) {
     if (typeof obj[i] == "function") {
-      wrapper[i] = wrapCallback(Cu.unwaiveXrays(obj[i]), win);
+      wrapper[i] = wrapCallback(obj[i]);
     } else {
       wrapper[i] = obj[i];
     }
   }
   return wrapper;
 }
 
-function disableAutoWrap(...objs) {
-  objs.forEach(x => noAutoWrap.add(x));
-}
-
 var WrapPrivileged = {
   wrap: wrapIfUnwrapped,
   unwrap: unwrapIfWrapped,
 
   isWrapper,
 
   wrapCallback,
   wrapCallbackObject,
-
-  disableAutoWrap,
 };
--- a/toolkit/components/passwordmgr/test/browser/head.js
+++ b/toolkit/components/passwordmgr/test/browser/head.js
@@ -125,17 +125,17 @@ async function submitFormAndGetResults(
         let field = doc.querySelector(sel);
         let gotInput = ContentTaskUtils.waitForEvent(
           field,
           "input",
           "Got input event on " + sel
         );
         // we don't get an input event if the new value == the old
         field.value = "###";
-        WrapPrivileged.wrap(field, this).setUserInput(value);
+        WrapPrivileged.wrap(field).setUserInput(value);
         await gotInput;
       } catch (ex) {
         throw new Error(
           `submitForm: Couldn't set value of field at: ${sel}: ${ex.message}`
         );
       }
     }
     form.submit();
--- a/toolkit/components/passwordmgr/test/mochitest/test_autofocus_js.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_autofocus_js.html
@@ -113,17 +113,18 @@ add_task(async function test_reopened_af
 add_task(async function test_not_reopened_after_selecting() {
   await SpecialPowers.spawn(getIframeBrowsingContext(window), [], function() {
     this.content.document.getElementById("form-basic-username").value = "";
     this.content.document.getElementById("form-basic-password").value = "";
   });
   listenForUnexpectedPopupShown();
 
   await SpecialPowers.spawn(getIframeBrowsingContext(window), [], function() {
-    let formFillController = SpecialPowers.getFormFillController();
+    let formFillController = SpecialPowers.Cc["@mozilla.org/satchel/form-fill-controller;1"].
+                             getService(SpecialPowers.Ci.nsIFormFillController);
     let usernameField = this.content.document.getElementById("form-basic-username");
     formFillController.markAsLoginManagerField(usernameField);
   });
 
   info("Waiting to see if a popupshown occurs");
   await new Promise(resolve => setTimeout(resolve, 1000));
 
   // Cleanup
--- a/toolkit/components/passwordmgr/test/mochitest/test_munged_values.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_munged_values.html
@@ -236,17 +236,17 @@ add_task(async function test_no_save_dia
   }
 });
 
 add_task(async function test_no_autofill_munged_username_matching_password() {
   // run this test with 2 matching logins from this origin so we don't autofill
   await add2logins();
 
   let allLogins = await LoginManager.getAllLogins();
-  let matchingLogins = Array.prototype.filter.call(allLogins, l => l.origin == ORG_ORIGIN);
+  let matchingLogins = allLogins.filter(l => l.origin == ORG_ORIGIN);
   is(matchingLogins.length, 2, "Expected number of matching logins");
 
   let bulletLogin = matchingLogins.find(l => l.username == "real••••user");
   ok(bulletLogin, "Found the real••••user login");
 
   let timesUsed = bulletLogin.timesUsed;
   let guid = bulletLogin.guid;
 
@@ -272,30 +272,30 @@ add_task(async function test_no_autofill
   });
 
   let submittedResult = await processedPromise;
   info("Got submittedResult: " + JSON.stringify(submittedResult));
 
   is(submittedResult.usernameField, null, "Check usernameField");
 
   let updatedLogins = await LoginManager.getAllLogins();
-  let updatedLogin = Array.prototype.find.call(updatedLogins, l => l.guid == guid);
+  let updatedLogin = updatedLogins.find(l => l.guid == guid);
   ok(updatedLogin, "Got the login via guid");
   is(updatedLogin.timesUsed, timesUsed + 1, "timesUsed was incremented");
 
   await popupShownPromise;
 });
 
 
 add_task(async function test_autofill_munged_username_matching_password() {
   // only a single matching login so we autofill the username
   await addSingleLogin();
 
   let allLogins = await LoginManager.getAllLogins();
-  let matchingLogins = Array.prototype.filter.call(allLogins, l => l.origin == ORG_ORIGIN);
+  let matchingLogins = allLogins.filter(l => l.origin == ORG_ORIGIN);
   is(matchingLogins.length, 1, "Expected number of matching logins");
 
   info("matched login: " + matchingLogins[0].username);
   let bulletLogin = matchingLogins.find(l => l.username == "real••••user");
   ok(bulletLogin, "Found the real••••user login");
 
   let timesUsed = bulletLogin.timesUsed;
   let guid = bulletLogin.guid;
@@ -321,17 +321,17 @@ add_task(async function test_autofill_mu
   });
 
   let submittedResult = await processedPromise;
   info("Got submittedResult: " + JSON.stringify(submittedResult));
 
   is(submittedResult.usernameField, null, "Check usernameField");
 
   let updatedLogins = await LoginManager.getAllLogins();
-  let updatedLogin = Array.prototype.find.call(updatedLogins, l => l.guid == guid);
+  let updatedLogin = updatedLogins.find(l => l.guid == guid);
   ok(updatedLogin, "Got the login via guid");
   is(updatedLogin.timesUsed, timesUsed + 1, "timesUsed was incremented");
 
   await popupShownPromise;
 });
 
 </script>
 
--- a/toolkit/content/tests/widgets/test_ua_widget_sandbox.html
+++ b/toolkit/content/tests/widgets/test_ua_widget_sandbox.html
@@ -19,19 +19,19 @@
 const content = document.getElementById("content");
 
 const div = content.appendChild(document.createElement("div"));
 div.attachShadow({ mode: "open"});
 SpecialPowers.wrap(div.shadowRoot).setIsUAWidget();
 
 const sandbox = SpecialPowers.Cu.getUAWidgetScope(SpecialPowers.wrap(div).nodePrincipal);
 
-SpecialPowers.setWrapped(sandbox, "info", SpecialPowers.wrapFor(info, sandbox));
-SpecialPowers.setWrapped(sandbox, "is", SpecialPowers.wrapFor(is, sandbox));
-SpecialPowers.setWrapped(sandbox, "ok", SpecialPowers.wrapFor(ok, sandbox));
+SpecialPowers.setWrapped(sandbox, "info", SpecialPowers.wrap(info));
+SpecialPowers.setWrapped(sandbox, "is", SpecialPowers.wrap(is));
+SpecialPowers.setWrapped(sandbox, "ok", SpecialPowers.wrap(ok));
 
 const sandboxScript = function(shadowRoot) {
   info("UA Widget scope tests");
   is(typeof window, "undefined", "The sandbox has no window");
   is(typeof document, "undefined", "The sandbox has no document");
 
   let element = shadowRoot.host;
   let doc = element.ownerDocument;