Backed out 2 changesets (bug 1526557, bug 1522244) for failing xpcshell at test_framebindings-02.js on a CLOSED TREE
authorAndreea Pavel <apavel@mozilla.com>
Thu, 28 Feb 2019 03:27:12 +0200
changeset 461684 d11fd5d6bda6aca0e7e5786a45471726dfdddb9a
parent 461683 67bef7d63d865cd66c8f7c836ed8a0b90da8215e
child 461685 de1481b9b6faab60a32f630fa50ec2a16db11773
push id35626
push usercsabou@mozilla.com
push dateThu, 28 Feb 2019 11:31:08 +0000
treeherdermozilla-central@2ea0c1db7e60 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1526557, 1522244
milestone67.0a1
backs out67bef7d63d865cd66c8f7c836ed8a0b90da8215e
09f23a363606830752a90a88dc452dd6d58ec10e
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 2 changesets (bug 1526557, bug 1522244) for failing xpcshell at test_framebindings-02.js on a CLOSED TREE Backed out changeset 67bef7d63d86 (bug 1526557) Backed out changeset 09f23a363606 (bug 1522244)
devtools/client/debugger/new/test/mochitest/browser.ini
devtools/client/debugger/new/test/mochitest/browser_dbg-worker-scopes.js
devtools/client/debugger/new/test/mochitest/examples/doc-worker-scopes.html
devtools/client/debugger/new/test/mochitest/examples/scopes-worker.js
devtools/server/actors/breakpoint.js
devtools/server/actors/object/previewers.js
devtools/server/actors/object/property-iterator.js
devtools/server/actors/object/utils.js
devtools/server/tests/unit/test_logpoint-01.js
devtools/server/tests/unit/test_logpoint-02.js
devtools/server/tests/unit/test_objectgrips-20.js
devtools/server/tests/unit/testactors.js
devtools/shared/DevToolsUtils.js
dom/workers/RuntimeService.cpp
--- a/devtools/client/debugger/new/test/mochitest/browser.ini
+++ b/devtools/client/debugger/new/test/mochitest/browser.ini
@@ -650,18 +650,16 @@ support-files =
   examples/pause-points.js
   examples/script-mutate.js
   examples/script-switching-02.js
   examples/script-switching-01.js
   examples/times2.js
   examples/doc-windowless-workers.html
   examples/doc-windowless-workers-early-breakpoint.html
   examples/simple-worker.js
-  examples/doc-worker-scopes.html
-  examples/scopes-worker.js
   examples/doc-event-handler.html
   examples/doc-eval-throw.html
 
 [browser_dbg-asm.js]
 [browser_dbg-async-stepping.js]
 [browser_dbg-sourcemapped-breakpoint-console.js]
 skip-if = (os == "win" && ccov) # Bug 1453549
 [browser_dbg-xhr-breakpoints.js]
@@ -769,11 +767,10 @@ skip-if = os == "win"
 [browser_dbg-tabs-without-urls.js]
 [browser_dbg-toggling-tools.js]
 [browser_dbg-react-app.js]
 skip-if = os == "win"
 [browser_dbg-wasm-sourcemaps.js]
 skip-if = true
 [browser_dbg-windowless-workers.js]
 [browser_dbg-windowless-workers-early-breakpoint.js]
-[browser_dbg-worker-scopes.js]
 [browser_dbg-event-handler.js]
 [browser_dbg-eval-throw.js]
deleted file mode 100644
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-worker-scopes.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function findNode(dbg, text) {
-  for (let index = 0;; index++) {
-    var elem = findElement(dbg, "scopeNode", index);
-    if (elem && elem.innerText == text) {
-      return elem;
-    }
-  }
-}
-
-function toggleNode(dbg, text) {
-  return toggleObjectInspectorNode(findNode(dbg, text));
-}
-
-function findNodeValue(dbg, text) {
-  for (let index = 0;; index++) {
-    var elem = findElement(dbg, "scopeNode", index);
-    if (elem && elem.innerText == text) {
-      return findElement(dbg, "scopeValue", index).innerText;
-    }
-  }
-}
-
-// Test that unusual objects have their contents shown in worker thread scopes.
-add_task(async function() {
-  const dbg = await initDebugger("doc-worker-scopes.html", "scopes-worker.js");
-  const workerSource = findSource(dbg, "scopes-worker.js");
-
-  await addBreakpoint(dbg, workerSource, 6);
-  invokeInTab("startWorker");
-  await waitForPaused(dbg, "scopes-worker.js");
-  await removeBreakpoint(dbg, workerSource.id, 6);
-
-  // We should be paused at the first line of simple-worker.js
-  assertPausedAtSourceAndLine(dbg, workerSource.id, 6);
-
-  await toggleNode(dbg, "var_array");
-  ok(findNodeValue(dbg, "0") == "\"mango\"", "array elem0");
-  ok(findNodeValue(dbg, "1") == "\"pamplemousse\"", "array elem1");
-  ok(findNodeValue(dbg, "2") == "\"pineapple\"", "array elem2");
-  await toggleNode(dbg, "var_array");
-
-  await toggleNode(dbg, "var_tarray");
-  ok(findNodeValue(dbg, "0") == "42", "tarray elem0");
-  ok(findNodeValue(dbg, "1") == "43", "tarray elem1");
-  ok(findNodeValue(dbg, "2") == "44", "tarray elem2");
-  await toggleNode(dbg, "var_tarray");
-
-  await toggleNode(dbg, "var_set");
-  await toggleNode(dbg, "<entries>");
-  ok(findNodeValue(dbg, "0") == "\"papaya\"", "set elem0");
-  ok(findNodeValue(dbg, "1") == "\"banana\"", "set elem1");
-  await toggleNode(dbg, "var_set");
-
-  await toggleNode(dbg, "var_map");
-  await toggleNode(dbg, "<entries>");
-  await toggleNode(dbg, "0");
-  ok(findNodeValue(dbg, "<key>"), "1");
-  ok(findNodeValue(dbg, "<value>"), "\"one\"");
-  await toggleNode(dbg, "0");
-  await toggleNode(dbg, "1");
-  ok(findNodeValue(dbg, "<key>"), "2");
-  ok(findNodeValue(dbg, "<value>"), "\"two\"");
-});
deleted file mode 100644
--- a/devtools/client/debugger/new/test/mochitest/examples/doc-worker-scopes.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-
-<script>
-startWorker();
-
-function startWorker() {
-  w = new Worker("scopes-worker.js");
-}
-</script>
-
-<body>
-Hello World!
-</body>
-</html>
deleted file mode 100644
--- a/devtools/client/debugger/new/test/mochitest/examples/scopes-worker.js
+++ /dev/null
@@ -1,8 +0,0 @@
-function f() {
-  var var_array = ["mango","pamplemousse","pineapple"];
-  var var_tarray = new Uint8Array([42,43,44]);
-  var var_set = new Set(["papaya","banana"]);
-  var var_map = new Map([[1,"one"],[2,"two"]]);
-  return 0;
-}
-f();
--- a/devtools/server/actors/breakpoint.js
+++ b/devtools/server/actors/breakpoint.js
@@ -108,30 +108,16 @@ BreakpointActor.prototype = {
             };
             this.threadActor._parent._consoleActor.onConsoleAPICall(message);
           });
         }
       }
     }
   },
 
-  // Get a string message to display when a frame evaluation throws.
-  getThrownMessage(completion) {
-    try {
-      if (completion.throw.getOwnPropertyDescriptor) {
-        return completion.throw.getOwnPropertyDescriptor("message").value;
-      } else if (completion.toString) {
-        return completion.toString();
-      }
-    } catch (ex) {
-      // ignore
-    }
-    return "Unknown exception";
-  },
-
   /**
    * Check if this breakpoint has a condition that doesn't error and
    * evaluates to true in frame.
    *
    * @param frame Debugger.Frame
    *        The frame to evaluate the condition in
    * @returns Object
    *          - result: boolean|undefined
@@ -141,19 +127,30 @@ BreakpointActor.prototype = {
    *          - message: string
    *            If the condition throws, this is the thrown message.
    */
   checkCondition: function(frame, condition) {
     const completion = frame.eval(condition);
     if (completion) {
       if (completion.throw) {
         // The evaluation failed and threw
+        let message = "Unknown exception";
+        try {
+          if (completion.throw.getOwnPropertyDescriptor) {
+            message = completion.throw.getOwnPropertyDescriptor("message")
+                      .value;
+          } else if (completion.toString) {
+            message = completion.toString();
+          }
+        } catch (ex) {
+          // ignore
+        }
         return {
           result: true,
-          message: this.getThrownMessage(completion),
+          message: message,
         };
       } else if (completion.yield) {
         assert(false, "Shouldn't ever get yield completions from an eval");
       } else {
         return { result: !!completion.return };
       }
     }
     // The evaluation was killed (possibly by the slow script dialog)
@@ -186,65 +183,51 @@ BreakpointActor.prototype = {
     // the spot at which popping started, ignore it.  See bug 970469.
     const locationAtFinish = frame.onPop && frame.onPop.generatedLocation;
     if (locationAtFinish &&
         locationAtFinish.generatedLine === generatedLine &&
         locationAtFinish.generatedColumn === generatedColumn) {
       return undefined;
     }
 
-    const reason = { type: "breakpoint", actors: [ this.actorID ] };
+    const reason = {};
     const { condition, logValue } = this.options || {};
 
-    // When replaying, breakpoints with log values are handled via
-    // _updateOptionsForScript.
-    if (logValue && this.threadActor.dbg.replaying) {
-      return undefined;
-    }
+    if (!condition && !logValue) {
+      reason.type = "breakpoint";
+      // TODO: add the rest of the breakpoints on that line (bug 676602).
+      reason.actors = [ this.actorID ];
+    } else {
+      // When replaying, breakpoints with log values are handled separately.
+      if (logValue && this.threadActor.dbg.replaying) {
+        return undefined;
+      }
 
-    if (condition) {
-      const { result, message } = this.checkCondition(frame, condition);
+      let condstr = condition;
+      if (logValue) {
+        // In the non-replaying case, log values are handled by treating them as
+        // conditions. console.log() never returns true so we will not pause.
+        condstr = condition
+          ? `(${condition}) && console.log(${logValue})`
+          : `console.log(${logValue})`;
+      }
+      const { result, message } = this.checkCondition(frame, condstr);
 
       if (result) {
-        if (message) {
+        if (!message) {
+          reason.type = "breakpoint";
+        } else {
           reason.type = "breakpointConditionThrown";
           reason.message = message;
         }
+        reason.actors = [ this.actorID ];
       } else {
         return undefined;
       }
     }
-
-    if (logValue) {
-      const completion = frame.eval(logValue);
-      let value;
-      if (!completion) {
-        // The evaluation was killed (possibly by the slow script dialog).
-        value = "Log value evaluation incomplete";
-      } else if ("return" in completion) {
-        value = completion.return;
-      } else {
-        value = this.getThrownMessage(completion);
-      }
-      if (value && typeof value.unsafeDereference === "function") {
-        value = value.unsafeDereference();
-      }
-
-      const message = {
-        filename: url,
-        lineNumber: generatedLine,
-        columnNumber: generatedColumn,
-        "arguments": [value],
-      };
-      this.threadActor._parent._consoleActor.onConsoleAPICall(message);
-
-      // Never stop at log points.
-      return undefined;
-    }
-
     return this.threadActor._pauseAndRespond(frame, reason);
   },
 
   delete: function() {
     // Remove from the breakpoint store.
     this.threadActor.breakpointActorMap.deleteActor(this.location);
     this.threadActor.threadLifetimePool.removeActor(this);
     // Remove the actual breakpoint from the associated scripts.
--- a/devtools/server/actors/object/previewers.js
+++ b/devtools/server/actors/object/previewers.js
@@ -124,35 +124,34 @@ const previewers = {
     if (hooks.getGripDepth() > 1) {
       return true;
     }
 
     const raw = obj.unsafeDereference();
     const items = grip.preview.items = [];
 
     for (let i = 0; i < length; ++i) {
-      if (raw && !isWorker) {
+      if (raw) {
         // Array Xrays filter out various possibly-unsafe properties (like
         // functions, and claim that the value is undefined instead. This
         // is generally the right thing for privileged code accessing untrusted
         // objects, but quite confusing for Object previews. So we manually
         // override this protection by waiving Xrays on the array, and re-applying
         // Xrays on any indexed value props that we pull off of it.
         const desc = Object.getOwnPropertyDescriptor(Cu.waiveXrays(raw), i);
         if (desc && !desc.get && !desc.set) {
           let value = Cu.unwaiveXrays(desc.value);
           value = ObjectUtils.makeDebuggeeValueIfNeeded(obj, value);
           items.push(hooks.createValueGrip(value));
         } else {
           items.push(null);
         }
       } else {
-        // Workers do not have access to Cu, and when recording/replaying we
-        // don't have a raw object. In either case we do not need to deal with
-        // xray wrappers.
+        // When recording/replaying we don't have a raw object, but also don't
+        // need to deal with Xrays into the debuggee compartment.
         const value = DevToolsUtils.getProperty(obj, i);
         items.push(hooks.createValueGrip(value));
       }
 
       if (items.length == OBJECT_PREVIEW_MAX_ITEMS) {
         break;
       }
     }
@@ -453,19 +452,18 @@ previewers.Object = [
 
     if (hooks.getGripDepth() > 1) {
       return true;
     }
 
     const raw = obj.unsafeDereference();
 
     // The raw object will be null/unavailable when interacting with a
-    // replaying execution, and Cu is unavailable in workers. In either case we
-    // do not need to worry about xrays.
-    if (raw && !isWorker) {
+    // replaying execution.
+    if (raw) {
       const global = Cu.getGlobalForObject(DebuggerServer);
       const classProto = global[obj.class].prototype;
       // The Xray machinery for TypedArrays denies indexed access on the grounds
       // that it's slow, and advises callers to do a structured clone instead.
       const safeView = Cu.cloneInto(classProto.subarray.call(raw, 0,
         OBJECT_PREVIEW_MAX_ITEMS), global);
       const items = grip.preview.items = [];
       for (let i = 0; i < safeView.length; i++) {
--- a/devtools/server/actors/object/property-iterator.js
+++ b/devtools/server/actors/object/property-iterator.js
@@ -108,21 +108,18 @@ const PropertyIteratorActor  = protocol.
     return this.slice({ start: 0, count: this.iterator.size });
   },
 });
 
 /**
  * Helper function to create a grip from a Map/Set entry
  */
 function gripFromEntry({ obj, hooks }, entry) {
-  if (!isWorker) {
-    entry = Cu.unwaiveXrays(entry);
-  }
   return hooks.createValueGrip(
-    ObjectUtils.makeDebuggeeValueIfNeeded(obj, entry));
+    ObjectUtils.makeDebuggeeValueIfNeeded(obj, Cu.unwaiveXrays(entry)));
 }
 
 function enumArrayProperties(objectActor, options) {
   return {
     size: ObjectUtils.getArrayLength(objectActor.obj),
     propertyName(index) {
       return index;
     },
@@ -249,47 +246,33 @@ function enumMapEntries(objectActor) {
   // Arrays, the semantics often deny access to the entires based on the
   // nature of the values. So we need waive Xrays for the iterator object
   // and the tupes, and then re-apply them on the underlying values until
   // we fix bug 1023984.
   //
   // Even then though, we might want to continue waiving Xrays here for the
   // same reason we do so for Arrays above - this filtering behavior is likely
   // to be more confusing than beneficial in the case of Object previews.
-  let keys, getValue;
-  if (isWorker) {
-    const keysIterator = DevToolsUtils.callPropertyOnObject(objectActor.obj, "keys");
-    keys = [...DevToolsUtils.makeDebuggeeIterator(keysIterator)];
-    const valuesIterator = DevToolsUtils.callPropertyOnObject(objectActor.obj, "values");
-    const values = [...DevToolsUtils.makeDebuggeeIterator(valuesIterator)];
-    const map = new Map();
-    for (let i = 0; i < keys.length; i++) {
-      map.set(keys[i], values[i]);
-    }
-    getValue = key => map.get(key);
-  } else {
-    const raw = objectActor.obj.unsafeDereference();
-    keys = [...Cu.waiveXrays(Map.prototype.keys.call(raw))];
-    getValue = key => Map.prototype.get.call(raw, key);
-  }
+  const raw = objectActor.obj.unsafeDereference();
 
+  const keys = [...Cu.waiveXrays(Map.prototype.keys.call(raw))];
   return {
     [Symbol.iterator]: function* () {
       for (const key of keys) {
-        const value = getValue(key);
+        const value = Map.prototype.get.call(raw, key);
         yield [ key, value ].map(val => gripFromEntry(objectActor, val));
       }
     },
     size: keys.length,
     propertyName(index) {
       return index;
     },
     propertyDescription(index) {
       const key = keys[index];
-      const val = getValue(key);
+      const val = Map.prototype.get.call(raw, key);
       return {
         enumerable: true,
         value: {
           type: "mapEntry",
           preview: {
             key: gripFromEntry(objectActor, key),
             value: gripFromEntry(objectActor, val),
           },
@@ -386,24 +369,18 @@ function enumSetEntries(objectActor) {
   // compartment. However, we _do_ have Xrays to Object now, so we end up
   // Xraying those temporary objects, and filtering access to |it.value|
   // based on whether or not it's Xrayable and/or callable, which breaks
   // the for/of iteration.
   //
   // This code is designed to handle untrusted objects, so we can safely
   // waive Xrays on the iterable, and relying on the Debugger machinery to
   // make sure we handle the resulting objects carefully.
-  let values;
-  if (isWorker) {
-    const iterator = DevToolsUtils.callPropertyOnObject(objectActor.obj, "values");
-    values = [...DevToolsUtils.makeDebuggeeIterator(iterator)];
-  } else {
-    const raw = objectActor.obj.unsafeDereference();
-    values = [...Cu.waiveXrays(Set.prototype.values.call(raw))];
-  }
+  const raw = objectActor.obj.unsafeDereference();
+  const values = [...Cu.waiveXrays(Set.prototype.values.call(raw))];
 
   return {
     [Symbol.iterator]: function* () {
       for (const item of values) {
         yield gripFromEntry(objectActor, item);
       }
     },
     size: values.length,
--- a/devtools/server/actors/object/utils.js
+++ b/devtools/server/actors/object/utils.js
@@ -166,22 +166,16 @@ function getArrayLength(object) {
   // Real arrays have a reliable `length` own property.
   if (object.class === "Array") {
     return DevToolsUtils.getProperty(object, "length");
   }
 
   // For typed arrays, `DevToolsUtils.getProperty` is not reliable because the `length`
   // getter could be shadowed by an own property, and `getOwnPropertyNames` is
   // unnecessarily slow. Obtain the `length` getter safely and call it manually.
-  if (isWorker) {
-    // Workers can't wrap debugger values into debuggees, so do the calculations
-    // in the debuggee itself.
-    const getter = object.proto.proto.getOwnPropertyDescriptor("length").get;
-    return getter.call(object).return;
-  }
   const typedProto = Object.getPrototypeOf(Uint8Array.prototype);
   const getter = Object.getOwnPropertyDescriptor(typedProto, "length").get;
   return getter.call(object.unsafeDereference());
 }
 
 /**
  * Returns true if the parameter is suitable to be an array index.
  *
--- a/devtools/server/tests/unit/test_logpoint-01.js
+++ b/devtools/server/tests/unit/test_logpoint-01.js
@@ -1,20 +1,18 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 /* eslint-disable no-shadow, max-nested-callbacks */
 
 "use strict";
 
 /**
- * Check that logpoints generate console messages.
+ * Check that logpoints call console.log.
  */
 
-const { getLastThreadActor } = require("xpcshell-test/testactors");
-
 var gDebuggee;
 var gClient;
 var gThreadClient;
 
 function run_test() {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-logpoint");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
@@ -24,44 +22,39 @@ function run_test() {
                              gThreadClient = threadClient;
                              test_simple_breakpoint();
                            });
   });
   do_test_pending();
 }
 
 function test_simple_breakpoint() {
-  let lastMessage;
-  getLastThreadActor()._parent._consoleActor = {
-    onConsoleAPICall(message) {
-      lastMessage = message;
-    },
-  };
-
   gThreadClient.addOneTimeListener("paused", async function(event, packet) {
     const source = await getSourceById(
       gThreadClient,
       packet.frame.where.actor
     );
 
     // Set a logpoint which should invoke console.log.
     gThreadClient.setBreakpoint({
       sourceUrl: source.url,
-      line: 3,
+      line: 4,
     }, { logValue: "a" });
 
     // Execute the rest of the code.
     gThreadClient.resume();
   });
 
+  // Sandboxes don't have a console available so we add our own.
   /* eslint-disable */
-  Cu.evalInSandbox("debugger;\n" + // 1
-                   "var a = 'three';\n" +  // 2
-                   "var b = 2;\n", // 3
+  Cu.evalInSandbox("var console = { log: v => { this.logValue = v } };\n" + // 1
+                   "debugger;\n" + // 2
+                   "var a = 'three';\n" +  // 3
+                   "var b = 2;\n", // 4
                    gDebuggee,
                    "1.8",
                    "test.js",
                    1);
   /* eslint-enable */
 
-  Assert.equal(lastMessage.arguments[0], "three");
+  Assert.equal(gDebuggee.logValue, "three");
   finishClient(gClient);
 }
--- a/devtools/server/tests/unit/test_logpoint-02.js
+++ b/devtools/server/tests/unit/test_logpoint-02.js
@@ -3,18 +3,16 @@
 /* eslint-disable no-shadow, max-nested-callbacks */
 
 "use strict";
 
 /**
  * Check that conditions are respected when specified in a logpoint.
  */
 
-const { getLastThreadActor } = require("xpcshell-test/testactors");
-
 var gDebuggee;
 var gClient;
 var gThreadClient;
 
 function run_test() {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-logpoint");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
@@ -24,46 +22,41 @@ function run_test() {
                              gThreadClient = threadClient;
                              test_simple_breakpoint();
                            });
   });
   do_test_pending();
 }
 
 function test_simple_breakpoint() {
-  let lastMessage;
-  getLastThreadActor()._parent._consoleActor = {
-    onConsoleAPICall(message) {
-      lastMessage = message;
-    },
-  };
-
   gThreadClient.addOneTimeListener("paused", async function(event, packet) {
     const source = await getSourceById(
       gThreadClient,
       packet.frame.where.actor
     );
 
     // Set a logpoint which should invoke console.log.
     gThreadClient.setBreakpoint({
       sourceUrl: source.url,
-      line: 4,
+      line: 5,
     }, { logValue: "a", condition: "a === 5" });
 
     // Execute the rest of the code.
     gThreadClient.resume();
   });
 
+  // Sandboxes don't have a console available so we add our own.
   /* eslint-disable */
-  Cu.evalInSandbox("debugger;\n" + // 1
-                   "var a = 1;\n" +  // 2
-                   "while (a < 10) {\n" + // 3
-                   "  a++;\n" + // 4
+  Cu.evalInSandbox("var console = { log: v => { this.logValue = v } };\n" + // 1
+                   "debugger;\n" + // 2
+                   "var a = 1;\n" +  // 3
+                   "while (a < 10) {\n" + // 4
+                   "  a++;\n" + // 5
                    "}",
                    gDebuggee,
                    "1.8",
                    "test.js",
                    1);
   /* eslint-enable */
 
-  Assert.equal(lastMessage.arguments[0], 5);
+  Assert.equal(gDebuggee.logValue, 5);
   finishClient(gClient);
 }
--- a/devtools/server/tests/unit/test_objectgrips-20.js
+++ b/devtools/server/tests/unit/test_objectgrips-20.js
@@ -140,30 +140,17 @@ add_task(threadClientTest(async ({ threa
     expectedNonIndexedProperties: [
       ["foo", "bar"],
       ["bar", "foo"],
       ["length", 2],
       ["buffer", DO_NOT_CHECK_VALUE],
       ["byteLength", 2],
       ["byteOffset", 0],
     ],
-  }];
-
-  for (const test of testCases) {
-    await test_object_grip(debuggee, client, threadClient, test);
-  }
-}));
-
-// These tests are not yet supported in workers.
-add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
-  debuggee.eval(function stopMe(arg1) {
-    debugger;
-  }.toString());
-
-  const testCases = [{
+  }, {
     evaledObject: `(() => {
       x = new Int8Array([1, 2]);
       Object.defineProperty(x, 'length', {value: 0});
       return x;
     })()`,
     expectedIndexedProperties: [["0", 1], ["1", 2]],
     expectedNonIndexedProperties: [
       ["length", 0],
@@ -179,17 +166,17 @@ add_task(threadClientTest(async ({ threa
     })()`,
     expectedIndexedProperties: [["0", 1], ["1", 2]],
     expectedNonIndexedProperties: [],
   }];
 
   for (const test of testCases) {
     await test_object_grip(debuggee, client, threadClient, test);
   }
-}, { doNotRunWorker: true }));
+}));
 
 async function test_object_grip(debuggee, dbgClient, threadClient, testData = {}) {
   const {
     evaledObject,
     expectedIndexedProperties,
     expectedNonIndexedProperties,
   } = testData;
 
--- a/devtools/server/tests/unit/testactors.js
+++ b/devtools/server/tests/unit/testactors.js
@@ -77,27 +77,21 @@ exports.createRootActor = function creat
     tabList: new TestTabList(connection),
     globalActorFactories: ActorRegistry.globalActorFactories,
   });
 
   root.applicationType = "xpcshell-tests";
   return root;
 };
 
-var gLastThreadActor;
-
-exports.getLastThreadActor = function() {
-  return gLastThreadActor;
-};
-
 function TestTargetActor(connection, global) {
   this.conn = connection;
   this._global = global;
   this._global.wrappedJSObject = global;
-  this.threadActor = gLastThreadActor = new ThreadActor(this, this._global);
+  this.threadActor = new ThreadActor(this, this._global);
   this.conn.addActor(this.threadActor);
   this._attached = false;
   this._extraActors = {};
   this.makeDebugger = makeDebugger.bind(null, {
     findDebuggees: () => [this._global],
     shouldAddNewGlobalAsDebuggee: g => {
       if (gAllowNewThreadGlobals) {
         return true;
--- a/devtools/shared/DevToolsUtils.js
+++ b/devtools/shared/DevToolsUtils.js
@@ -846,22 +846,8 @@ function callPropertyOnObject(object, na
   }
   if ("throw" in result) {
     throw result.throw;
   }
   return result.return;
 }
 
 exports.callPropertyOnObject = callPropertyOnObject;
-
-// Convert a Debugger.Object wrapping an iterator into an iterator in the
-// debugger's realm.
-function* makeDebuggeeIterator(object) {
-  while (true) {
-    const nextValue = callPropertyOnObject(object, "next");
-    if (exports.getProperty(nextValue, "done")) {
-      break;
-    }
-    yield exports.getProperty(nextValue, "value");
-  }
-}
-
-exports.makeDebuggeeIterator = makeDebuggeeIterator;
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -817,18 +817,17 @@ static bool PreserveWrapper(JSContext* c
 
   return mozilla::dom::TryPreserveWrapper(obj);
 }
 
 JSObject* Wrap(JSContext* cx, JS::HandleObject existing, JS::HandleObject obj) {
   JSObject* targetGlobal = JS::CurrentGlobalOrNull(cx);
   if (!IsWorkerDebuggerGlobal(targetGlobal) &&
       !IsWorkerDebuggerSandbox(targetGlobal)) {
-    JS_ReportErrorASCII(cx, "There should be no edges from the debuggee to the debugger.");
-    return nullptr;
+    MOZ_CRASH("There should be no edges from the debuggee to the debugger.");
   }
 
   // Note: the JS engine unwraps CCWs before calling this callback.
   JSObject* originGlobal = JS::GetNonCCWObjectGlobal(obj);
 
   const js::Wrapper* wrapper = nullptr;
   if (IsWorkerDebuggerGlobal(originGlobal) ||
       IsWorkerDebuggerSandbox(originGlobal)) {