summaryrefslogtreecommitdiffstats
path: root/devtools/server/actors
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:14:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:14:29 +0000
commitfbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 (patch)
tree4c1ccaf5486d4f2009f9a338a98a83e886e29c97 /devtools/server/actors
parentReleasing progress-linux version 124.0.1-1~progress7.99u1. (diff)
downloadfirefox-fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8.tar.xz
firefox-fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8.zip
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/server/actors')
-rw-r--r--devtools/server/actors/accessibility/accessible.js8
-rw-r--r--devtools/server/actors/addon/addons.js10
-rw-r--r--devtools/server/actors/addon/webextension-inspected-window.js4
-rw-r--r--devtools/server/actors/animation-type-longhand.js1
-rw-r--r--devtools/server/actors/animation.js2
-rw-r--r--devtools/server/actors/breakpoint.js2
-rw-r--r--devtools/server/actors/descriptors/tab.js13
-rw-r--r--devtools/server/actors/descriptors/webextension.js6
-rw-r--r--devtools/server/actors/descriptors/worker.js3
-rw-r--r--devtools/server/actors/device.js3
-rw-r--r--devtools/server/actors/heap-snapshot-file.js2
-rw-r--r--devtools/server/actors/highlighters/css/highlighters.css4
-rw-r--r--devtools/server/actors/highlighters/shapes.js19
-rw-r--r--devtools/server/actors/highlighters/tabbing-order.js8
-rw-r--r--devtools/server/actors/inspector/constants.js2
-rw-r--r--devtools/server/actors/inspector/event-collector.js2
-rw-r--r--devtools/server/actors/inspector/inspector.js7
-rw-r--r--devtools/server/actors/inspector/walker.js44
-rw-r--r--devtools/server/actors/manifest.js10
-rw-r--r--devtools/server/actors/network-monitor/channel-event-sink.js5
-rw-r--r--devtools/server/actors/network-monitor/network-event-actor.js19
-rw-r--r--devtools/server/actors/object.js10
-rw-r--r--devtools/server/actors/object/previewers.js24
-rw-r--r--devtools/server/actors/object/property-iterator.js32
-rw-r--r--devtools/server/actors/objects-manager.js2
-rw-r--r--devtools/server/actors/page-style.js6
-rw-r--r--devtools/server/actors/preference.js2
-rw-r--r--devtools/server/actors/reflow.js4
-rw-r--r--devtools/server/actors/resources/extensions-backgroundscript-status.js2
-rw-r--r--devtools/server/actors/resources/network-events-content.js14
-rw-r--r--devtools/server/actors/resources/network-events-stacktraces.js19
-rw-r--r--devtools/server/actors/resources/network-events.js27
-rw-r--r--devtools/server/actors/resources/parent-process-document-event.js2
-rw-r--r--devtools/server/actors/resources/server-sent-events.js2
-rw-r--r--devtools/server/actors/resources/sources.js14
-rw-r--r--devtools/server/actors/resources/storage/extension-storage.js10
-rw-r--r--devtools/server/actors/resources/storage/indexed-db.js12
-rw-r--r--devtools/server/actors/resources/thread-states.js18
-rw-r--r--devtools/server/actors/resources/utils/content-process-storage.js12
-rw-r--r--devtools/server/actors/resources/utils/nsi-console-listener-watcher.js10
-rw-r--r--devtools/server/actors/resources/utils/parent-process-storage.js3
-rw-r--r--devtools/server/actors/resources/websockets.js4
-rw-r--r--devtools/server/actors/root.js2
-rw-r--r--devtools/server/actors/source.js6
-rw-r--r--devtools/server/actors/target-configuration.js3
-rw-r--r--devtools/server/actors/targets/content-process.js12
-rw-r--r--devtools/server/actors/targets/session-data-processors/blackboxing.js2
-rw-r--r--devtools/server/actors/targets/session-data-processors/breakpoints.js14
-rw-r--r--devtools/server/actors/targets/session-data-processors/event-breakpoints.js2
-rw-r--r--devtools/server/actors/targets/session-data-processors/resources.js2
-rw-r--r--devtools/server/actors/targets/session-data-processors/target-configuration.js9
-rw-r--r--devtools/server/actors/targets/session-data-processors/thread-configuration.js21
-rw-r--r--devtools/server/actors/targets/session-data-processors/xhr-breakpoints.js2
-rw-r--r--devtools/server/actors/targets/target-actor-registry.sys.mjs2
-rw-r--r--devtools/server/actors/targets/window-global.js26
-rw-r--r--devtools/server/actors/targets/worker.js2
-rw-r--r--devtools/server/actors/thread-configuration.js26
-rw-r--r--devtools/server/actors/thread.js111
-rw-r--r--devtools/server/actors/tracer.js154
-rw-r--r--devtools/server/actors/utils/custom-formatters.js4
-rw-r--r--devtools/server/actors/utils/inactive-property-helper.js39
-rw-r--r--devtools/server/actors/utils/logEvent.js4
-rw-r--r--devtools/server/actors/utils/sources-manager.js13
-rw-r--r--devtools/server/actors/utils/stylesheets-manager.js17
-rw-r--r--devtools/server/actors/watcher.js21
-rw-r--r--devtools/server/actors/watcher/WatcherRegistry.sys.mjs84
-rw-r--r--devtools/server/actors/watcher/target-helpers/content-process-jsprocessactor-startup.js26
-rw-r--r--devtools/server/actors/watcher/target-helpers/frame-helper.js11
-rw-r--r--devtools/server/actors/watcher/target-helpers/moz.build1
-rw-r--r--devtools/server/actors/watcher/target-helpers/process-helper.js372
-rw-r--r--devtools/server/actors/webbrowser.js14
-rw-r--r--devtools/server/actors/webconsole.js2
-rw-r--r--devtools/server/actors/webconsole/commands/experimental-commands.ftl22
-rw-r--r--devtools/server/actors/webconsole/commands/manager.js35
-rw-r--r--devtools/server/actors/webconsole/eager-ecma-allowlist.js23
-rw-r--r--devtools/server/actors/webconsole/eval-with-debugger.js20
-rw-r--r--devtools/server/actors/webconsole/listeners/console-file-activity.js2
-rw-r--r--devtools/server/actors/webconsole/listeners/document-events.js10
-rw-r--r--devtools/server/actors/worker/service-worker-registration-list.js7
-rw-r--r--devtools/server/actors/worker/service-worker-registration.js5
-rw-r--r--devtools/server/actors/worker/worker-descriptor-actor-list.js3
81 files changed, 838 insertions, 696 deletions
diff --git a/devtools/server/actors/accessibility/accessible.js b/devtools/server/actors/accessibility/accessible.js
index 1866d0a91b..451fa7f99a 100644
--- a/devtools/server/actors/accessibility/accessible.js
+++ b/devtools/server/actors/accessibility/accessible.js
@@ -67,11 +67,9 @@ loader.lazyGetter(
() =>
ChromeUtils.importESModule(
"resource://gre/modules/ContentDOMReference.sys.mjs",
- {
- // ContentDOMReference needs to be retrieved from the shared global
- // since it is a shared singleton.
- loadInDevToolsLoader: false,
- }
+ // ContentDOMReference needs to be retrieved from the shared global
+ // since it is a shared singleton.
+ { global: "shared" }
).ContentDOMReference
);
diff --git a/devtools/server/actors/addon/addons.js b/devtools/server/actors/addon/addons.js
index 95a3738d61..9d37df93e4 100644
--- a/devtools/server/actors/addon/addons.js
+++ b/devtools/server/actors/addon/addons.js
@@ -11,10 +11,11 @@ const {
const { AddonManager } = ChromeUtils.importESModule(
"resource://gre/modules/AddonManager.sys.mjs",
- { loadInDevToolsLoader: false }
+ { global: "shared" }
);
const { FileUtils } = ChromeUtils.importESModule(
- "resource://gre/modules/FileUtils.sys.mjs"
+ "resource://gre/modules/FileUtils.sys.mjs",
+ { global: "contextual" }
);
// This actor is used by DevTools as well as external tools such as webext-run
@@ -43,12 +44,13 @@ class AddonsActor extends Actor {
// so for now, there is no chance of calling this on Android.
if (openDevTools) {
// This module is typically loaded in the loader spawn by DevToolsStartup,
- // in a distinct compartment thanks to useDistinctSystemPrincipalLoader and loadInDevToolsLoader flag.
+ // in a distinct compartment thanks to useDistinctSystemPrincipalLoader
+ // and global flag.
// But here we want to reuse the shared module loader.
// We do not want to load devtools.js in the server's distinct module loader.
const loader = ChromeUtils.importESModule(
"resource://devtools/shared/loader/Loader.sys.mjs",
- { loadInDevToolsLoader: false }
+ { global: "shared" }
);
const {
gDevTools,
diff --git a/devtools/server/actors/addon/webextension-inspected-window.js b/devtools/server/actors/addon/webextension-inspected-window.js
index e69a206c9d..041045eec0 100644
--- a/devtools/server/actors/addon/webextension-inspected-window.js
+++ b/devtools/server/actors/addon/webextension-inspected-window.js
@@ -218,7 +218,7 @@ class CustomizedReload {
return this.waitForReloadCompleted;
}
- observe(subject, topic, data) {
+ observe(subject, topic) {
if (topic !== "initial-document-element-inserted") {
return;
}
@@ -319,7 +319,7 @@ class WebExtensionInspectedWindowActor extends Actor {
this.targetActor = targetActor;
}
- destroy(conn) {
+ destroy() {
super.destroy();
if (this.customizedReload) {
diff --git a/devtools/server/actors/animation-type-longhand.js b/devtools/server/actors/animation-type-longhand.js
index febf8457ad..6da49c7b4b 100644
--- a/devtools/server/actors/animation-type-longhand.js
+++ b/devtools/server/actors/animation-type-longhand.js
@@ -258,6 +258,7 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
"scroll-timeline-axis",
"scroll-timeline-name",
"size",
+ "transition-behavior",
"transition-delay",
"transition-duration",
"transition-property",
diff --git a/devtools/server/actors/animation.js b/devtools/server/actors/animation.js
index d8de85fd73..89a2f5e84d 100644
--- a/devtools/server/actors/animation.js
+++ b/devtools/server/actors/animation.js
@@ -171,7 +171,7 @@ class AnimationPlayerActor extends Actor {
*/
release() {}
- form(detail) {
+ form() {
const data = this.getCurrentState();
data.actor = this.actorID;
diff --git a/devtools/server/actors/breakpoint.js b/devtools/server/actors/breakpoint.js
index d1a469658c..bfa563bf55 100644
--- a/devtools/server/actors/breakpoint.js
+++ b/devtools/server/actors/breakpoint.js
@@ -90,7 +90,7 @@ class BreakpointActor {
/**
* Called on changes to this breakpoint's script offsets or options.
*/
- _newOffsetsOrOptions(script, offsets, oldOptions) {
+ _newOffsetsOrOptions(script, offsets) {
// Clear any existing handler first in case this is called multiple times
// after options change.
for (const offset of offsets) {
diff --git a/devtools/server/actors/descriptors/tab.js b/devtools/server/actors/descriptors/tab.js
index ea20d3fb36..f5980126cb 100644
--- a/devtools/server/actors/descriptors/tab.js
+++ b/devtools/server/actors/descriptors/tab.js
@@ -21,12 +21,17 @@ const {
connectToFrame,
} = require("resource://devtools/server/connectors/frame-connector.js");
const lazy = {};
-ChromeUtils.defineESModuleGetters(lazy, {
- PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
-});
+ChromeUtils.defineESModuleGetters(
+ lazy,
+ {
+ PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
+ },
+ { global: "contextual" }
+);
const { AppConstants } = ChromeUtils.importESModule(
- "resource://gre/modules/AppConstants.sys.mjs"
+ "resource://gre/modules/AppConstants.sys.mjs",
+ { global: "contextual" }
);
const {
createBrowserElementSessionContext,
diff --git a/devtools/server/actors/descriptors/webextension.js b/devtools/server/actors/descriptors/webextension.js
index 56e4abfc41..b202036aef 100644
--- a/devtools/server/actors/descriptors/webextension.js
+++ b/devtools/server/actors/descriptors/webextension.js
@@ -28,13 +28,13 @@ const lazy = {};
loader.lazyGetter(lazy, "AddonManager", () => {
return ChromeUtils.importESModule(
"resource://gre/modules/AddonManager.sys.mjs",
- { loadInDevToolsLoader: false }
+ { global: "shared" }
).AddonManager;
});
loader.lazyGetter(lazy, "ExtensionParent", () => {
return ChromeUtils.importESModule(
"resource://gre/modules/ExtensionParent.sys.mjs",
- { loadInDevToolsLoader: false }
+ { global: "shared" }
).ExtensionParent;
});
loader.lazyRequireGetter(
@@ -202,7 +202,7 @@ class WebExtensionDescriptorActor extends Actor {
*
* bypassCache has no impact for addon reloads.
*/
- reloadDescriptor({ bypassCache }) {
+ reloadDescriptor() {
return this.reload();
}
diff --git a/devtools/server/actors/descriptors/worker.js b/devtools/server/actors/descriptors/worker.js
index 89ca918e05..4c8689fac8 100644
--- a/devtools/server/actors/descriptors/worker.js
+++ b/devtools/server/actors/descriptors/worker.js
@@ -23,7 +23,8 @@ const {
DevToolsServer,
} = require("resource://devtools/server/devtools-server.js");
const { XPCOMUtils } = ChromeUtils.importESModule(
- "resource://gre/modules/XPCOMUtils.sys.mjs"
+ "resource://gre/modules/XPCOMUtils.sys.mjs",
+ { global: "contextual" }
);
const {
createWorkerSessionContext,
diff --git a/devtools/server/actors/device.js b/devtools/server/actors/device.js
index 2aa05959e5..69ec02a3ec 100644
--- a/devtools/server/actors/device.js
+++ b/devtools/server/actors/device.js
@@ -12,7 +12,8 @@ const {
} = require("resource://devtools/server/devtools-server.js");
const { getSystemInfo } = require("resource://devtools/shared/system.js");
const { AppConstants } = ChromeUtils.importESModule(
- "resource://gre/modules/AppConstants.sys.mjs"
+ "resource://gre/modules/AppConstants.sys.mjs",
+ { global: "contextual" }
);
exports.DeviceActor = class DeviceActor extends Actor {
diff --git a/devtools/server/actors/heap-snapshot-file.js b/devtools/server/actors/heap-snapshot-file.js
index f3fd9242b2..942f72a98b 100644
--- a/devtools/server/actors/heap-snapshot-file.js
+++ b/devtools/server/actors/heap-snapshot-file.js
@@ -27,7 +27,7 @@ loader.lazyRequireGetter(
* system.
*/
exports.HeapSnapshotFileActor = class HeapSnapshotFileActor extends Actor {
- constructor(conn, parent) {
+ constructor(conn) {
super(conn, heapSnapshotFileSpec);
if (
diff --git a/devtools/server/actors/highlighters/css/highlighters.css b/devtools/server/actors/highlighters/css/highlighters.css
index 33c8a04aae..04584e4bf1 100644
--- a/devtools/server/actors/highlighters/css/highlighters.css
+++ b/devtools/server/actors/highlighters/css/highlighters.css
@@ -1010,12 +1010,12 @@ button.paused-dbg-resume-button {
}
.accessible-infobar-audit .accessible-audit.WARNING::before {
- background-image: url(chrome://devtools/skin/images/alert-small.svg);
+ background-image: url(resource://devtools-shared-images/alert-small.svg);
fill: var(--yellow-60);
}
.accessible-infobar-audit .accessible-audit.BEST_PRACTICES::before {
- background-image: url(chrome://devtools/skin/images/info-small.svg);
+ background-image: url(resource://devtools-shared-images/info-small.svg);
}
.accessible-infobar-name {
diff --git a/devtools/server/actors/highlighters/shapes.js b/devtools/server/actors/highlighters/shapes.js
index a77e8c31be..6cc9194f57 100644
--- a/devtools/server/actors/highlighters/shapes.js
+++ b/devtools/server/actors/highlighters/shapes.js
@@ -519,7 +519,7 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
}
// eslint-disable-next-line complexity
- handleEvent(event, id) {
+ handleEvent(event) {
// No event handling if the highlighter is hidden
if (this.areShapesHidden()) {
return;
@@ -1222,7 +1222,7 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
coordinates.splice(point, 1);
let polygonDef = this.fillRule ? `${this.fillRule}, ` : "";
polygonDef += coordinates
- .map((coords, i) => {
+ .map(coords => {
return `${coords[0]} ${coords[1]}`;
})
.join(", ");
@@ -2735,11 +2735,8 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
/**
* Update the SVG polygon to fit the CSS polygon.
- * @param {Number} width the width of the element quads
- * @param {Number} height the height of the element quads
- * @param {Number} zoom the zoom level of the window
*/
- _updatePolygonShape(width, height, zoom) {
+ _updatePolygonShape() {
// Draw and show the polygon.
const points = this.coordinates.map(point => point.join(",")).join(" ");
@@ -2758,11 +2755,8 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
/**
* Update the SVG ellipse to fit the CSS circle or ellipse.
- * @param {Number} width the width of the element quads
- * @param {Number} height the height of the element quads
- * @param {Number} zoom the zoom level of the window
*/
- _updateEllipseShape(width, height, zoom) {
+ _updateEllipseShape() {
const { rx, ry, cx, cy } = this.coordinates;
const ellipseEl = this.getElement("ellipse");
ellipseEl.setAttribute("rx", rx);
@@ -2788,11 +2782,8 @@ class ShapesHighlighter extends AutoRefreshHighlighter {
/**
* Update the SVG rect to fit the CSS inset.
- * @param {Number} width the width of the element quads
- * @param {Number} height the height of the element quads
- * @param {Number} zoom the zoom level of the window
*/
- _updateInsetShape(width, height, zoom) {
+ _updateInsetShape() {
const { top, left, right, bottom } = this.coordinates;
const rectEl = this.getElement("rect");
rectEl.setAttribute("x", left);
diff --git a/devtools/server/actors/highlighters/tabbing-order.js b/devtools/server/actors/highlighters/tabbing-order.js
index ab96d30fe6..ccc70779bb 100644
--- a/devtools/server/actors/highlighters/tabbing-order.js
+++ b/devtools/server/actors/highlighters/tabbing-order.js
@@ -11,11 +11,9 @@ loader.lazyGetter(
() =>
ChromeUtils.importESModule(
"resource://gre/modules/ContentDOMReference.sys.mjs",
- {
- // ContentDOMReference needs to be retrieved from the shared global
- // since it is a shared singleton.
- loadInDevToolsLoader: false,
- }
+ // ContentDOMReference needs to be retrieved from the shared global
+ // since it is a shared singleton.
+ { global: "shared" }
).ContentDOMReference
);
loader.lazyRequireGetter(
diff --git a/devtools/server/actors/inspector/constants.js b/devtools/server/actors/inspector/constants.js
index c253c67b02..b55cd58389 100644
--- a/devtools/server/actors/inspector/constants.js
+++ b/devtools/server/actors/inspector/constants.js
@@ -10,7 +10,7 @@
*
* const someListener = () => {};
* someListener[EXCLUDED_LISTENER] = true;
- * eventListenerService.addSystemEventListener(node, "event", someListener);
+ * node.addEventListener("event", someListener);
*/
const EXCLUDED_LISTENER = Symbol("event-collector-excluded-listener");
diff --git a/devtools/server/actors/inspector/event-collector.js b/devtools/server/actors/inspector/event-collector.js
index 4ee8dc388f..7ae7ac45d7 100644
--- a/devtools/server/actors/inspector/event-collector.js
+++ b/devtools/server/actors/inspector/event-collector.js
@@ -241,7 +241,7 @@ class MainEventCollector {
* @return {Array}
* An array of event handlers.
*/
- getListeners(node, { checkOnly }) {
+ getListeners(_node, { checkOnly: _checkOnly }) {
throw new Error("You have to implement the method getListeners()!");
}
diff --git a/devtools/server/actors/inspector/inspector.js b/devtools/server/actors/inspector/inspector.js
index cdfa892889..95f7f76622 100644
--- a/devtools/server/actors/inspector/inspector.js
+++ b/devtools/server/actors/inspector/inspector.js
@@ -56,7 +56,8 @@ const {
} = require("resource://devtools/shared/specs/inspector.js");
const { setTimeout } = ChromeUtils.importESModule(
- "resource://gre/modules/Timer.sys.mjs"
+ "resource://gre/modules/Timer.sys.mjs",
+ { global: "contextual" }
);
const {
LongStringActor,
@@ -181,7 +182,7 @@ class InspectorActor extends Actor {
return this._pageStylePromise;
}
- this._pageStylePromise = this.getWalker().then(walker => {
+ this._pageStylePromise = this.getWalker().then(() => {
const pageStyle = new PageStyleActor(this);
this.manage(pageStyle);
return pageStyle;
@@ -263,7 +264,7 @@ class InspectorActor extends Actor {
return url;
}
- const baseURI = Services.io.newURI(document.location.href);
+ const baseURI = Services.io.newURI(document.baseURI);
return Services.io.newURI(url, null, baseURI).spec;
}
diff --git a/devtools/server/actors/inspector/walker.js b/devtools/server/actors/inspector/walker.js
index f8da1385e9..50df1720b7 100644
--- a/devtools/server/actors/inspector/walker.js
+++ b/devtools/server/actors/inspector/walker.js
@@ -111,11 +111,9 @@ if (!isWorker) {
() =>
ChromeUtils.importESModule(
"resource://gre/modules/ContentDOMReference.sys.mjs",
- {
- // ContentDOMReference needs to be retrieved from the shared global
- // since it is a shared singleton.
- loadInDevToolsLoader: false,
- }
+ // ContentDOMReference needs to be retrieved from the shared global
+ // since it is a shared singleton.
+ { global: "shared" }
).ContentDOMReference
);
}
@@ -341,7 +339,11 @@ class WalkerActor extends Actor {
return {
actor: this.actorID,
root: this.rootNode.form(),
- traits: {},
+ traits: {
+ // @backward-compat { version 125 } Indicate to the client that it can use getIdrefNode.
+ // This trait can be removed once 125 hits release.
+ hasGetIdrefNode: true,
+ },
};
}
@@ -524,7 +526,7 @@ class WalkerActor extends Actor {
* When a custom element is defined, send a customElementDefined mutation for all the
* NodeActors using this tag name.
*/
- onCustomElementDefined({ name, actors }) {
+ onCustomElementDefined({ actors }) {
actors.forEach(actor =>
this.queueMutation({
target: actor.actorID,
@@ -534,7 +536,7 @@ class WalkerActor extends Actor {
);
}
- _onReflows(reflows) {
+ _onReflows() {
// Going through the nodes the walker knows about, see which ones have had their
// containerType, display, scrollable or overflow state changed and send events if any.
const containerTypeChanges = [];
@@ -1070,6 +1072,32 @@ class WalkerActor extends Actor {
}
/**
+ * Return the node in the baseNode rootNode matching the passed id referenced in a
+ * idref/idreflist attribute, as those are scoped within a shadow root.
+ *
+ * @param NodeActor baseNode
+ * @param string id
+ */
+ getIdrefNode(baseNode, id) {
+ if (isNodeDead(baseNode)) {
+ return {};
+ }
+
+ // Get the document or the shadow root for baseNode
+ const rootNode = baseNode.rawNode.getRootNode({ composed: false });
+ if (!rootNode) {
+ return {};
+ }
+
+ const node = rootNode.getElementById(id);
+ if (!node) {
+ return {};
+ }
+
+ return this.attachElement(node);
+ }
+
+ /**
* Get a list of nodes that match the given selector in all known frames of
* the current content page.
* @param {String} selector.
diff --git a/devtools/server/actors/manifest.js b/devtools/server/actors/manifest.js
index 5436d4a53a..183ce1edea 100644
--- a/devtools/server/actors/manifest.js
+++ b/devtools/server/actors/manifest.js
@@ -11,9 +11,13 @@ const {
const lazy = {};
-ChromeUtils.defineESModuleGetters(lazy, {
- ManifestObtainer: "resource://gre/modules/ManifestObtainer.sys.mjs",
-});
+ChromeUtils.defineESModuleGetters(
+ lazy,
+ {
+ ManifestObtainer: "resource://gre/modules/ManifestObtainer.sys.mjs",
+ },
+ { global: "contextual" }
+);
/**
* An actor for a Web Manifest
diff --git a/devtools/server/actors/network-monitor/channel-event-sink.js b/devtools/server/actors/network-monitor/channel-event-sink.js
index 8ff00302f9..3db6bf148e 100644
--- a/devtools/server/actors/network-monitor/channel-event-sink.js
+++ b/devtools/server/actors/network-monitor/channel-event-sink.js
@@ -5,11 +5,12 @@
"use strict";
const { ComponentUtils } = ChromeUtils.importESModule(
- "resource://gre/modules/ComponentUtils.sys.mjs"
+ "resource://gre/modules/ComponentUtils.sys.mjs",
+ { global: "contextual" }
);
/**
- * This is a nsIChannelEventSink implementation that monitors channel redirects and
+ * THIS is a nsIChannelEventSink implementation that monitors channel redirects and
* informs the registered "collectors" about the old and new channels.
*/
const SINK_CLASS_DESCRIPTION = "NetworkMonitor Channel Event Sink";
diff --git a/devtools/server/actors/network-monitor/network-event-actor.js b/devtools/server/actors/network-monitor/network-event-actor.js
index e59738dd38..38607279d4 100644
--- a/devtools/server/actors/network-monitor/network-event-actor.js
+++ b/devtools/server/actors/network-monitor/network-event-actor.js
@@ -18,10 +18,14 @@ const {
const lazy = {};
-ChromeUtils.defineESModuleGetters(lazy, {
- NetworkUtils:
- "resource://devtools/shared/network-observer/NetworkUtils.sys.mjs",
-});
+ChromeUtils.defineESModuleGetters(
+ lazy,
+ {
+ NetworkUtils:
+ "resource://devtools/shared/network-observer/NetworkUtils.sys.mjs",
+ },
+ { global: "contextual" }
+);
const CONTENT_TYPE_REGEXP = /^content-type/i;
@@ -559,13 +563,8 @@ class NetworkEventActor extends Actor {
* @param object content
* The response content.
* @param object
- * - boolean discardedResponseBody
- * Tells if the response content was recorded or not.
*/
- addResponseContent(
- content,
- { discardResponseBody, blockedReason, blockingExtension }
- ) {
+ addResponseContent(content, { blockedReason, blockingExtension }) {
// Ignore calls when this actor is already destroyed
if (this.isDestroyed()) {
return;
diff --git a/devtools/server/actors/object.js b/devtools/server/actors/object.js
index 9b52c4ebe7..1d16eb2b75 100644
--- a/devtools/server/actors/object.js
+++ b/devtools/server/actors/object.js
@@ -63,11 +63,9 @@ if (!isWorker) {
() =>
ChromeUtils.importESModule(
"resource://gre/modules/ContentDOMReference.sys.mjs",
- {
- // ContentDOMReference needs to be retrieved from the shared global
- // since it is a shared singleton.
- loadInDevToolsLoader: false,
- }
+ // ContentDOMReference needs to be retrieved from the shared global
+ // since it is a shared singleton.
+ { global: "shared" }
).ContentDOMReference
);
}
@@ -171,7 +169,7 @@ class ObjectActor extends Actor {
}
// Only process custom formatters if the feature is enabled.
- if (this.thread?._parent?.customFormatters) {
+ if (this.thread?.targetActor?.customFormatters) {
const result = customFormatterHeader(this);
if (result) {
const { formatter, ...header } = result;
diff --git a/devtools/server/actors/object/previewers.js b/devtools/server/actors/object/previewers.js
index 451858a826..55217a72ee 100644
--- a/devtools/server/actors/object/previewers.js
+++ b/devtools/server/actors/object/previewers.js
@@ -612,6 +612,30 @@ const previewers = {
return true;
},
],
+
+ CustomStateSet: [
+ function(objectActor, grip) {
+ const size = DevToolsUtils.getProperty(objectActor.obj, "size");
+ if (typeof size != "number") {
+ return false;
+ }
+
+ grip.preview = {
+ kind: "ArrayLike",
+ length: size,
+ };
+
+ const items = (grip.preview.items = []);
+ for (const item of PropertyIterators.enumCustomStateSetEntries(objectActor)) {
+ items.push(item);
+ if (items.length == OBJECT_PREVIEW_MAX_ITEMS) {
+ break;
+ }
+ }
+
+ return true;
+ },
+ ],
};
/**
diff --git a/devtools/server/actors/object/property-iterator.js b/devtools/server/actors/object/property-iterator.js
index 7bd2c0a704..e7a4d2c041 100644
--- a/devtools/server/actors/object/property-iterator.js
+++ b/devtools/server/actors/object/property-iterator.js
@@ -75,6 +75,8 @@ class PropertyIteratorActor extends Actor {
this.iterator = enumMidiInputMapEntries(objectActor);
} else if (cls == "MIDIOutputMap") {
this.iterator = enumMidiOutputMapEntries(objectActor);
+ } else if (cls == "CustomStateSet") {
+ this.iterator = enumCustomStateSetEntries(objectActor);
} else {
throw new Error(
"Unsupported class to enumerate entries from: " + cls
@@ -658,6 +660,35 @@ function enumWeakSetEntries(objectActor) {
};
}
+function enumCustomStateSetEntries(objectActor) {
+ let raw = objectActor.obj.unsafeDereference();
+ // We need to waive `raw` as we can't get the iterator from the Xray for SetLike (See Bug 1173651).
+ // We also need to waive Xrays on the result of the call to `values` as we don't have
+ // Xrays to Iterator objects (see Bug 1023984)
+ const values = Array.from(
+ waiveXrays(CustomStateSet.prototype.values.call(waiveXrays(raw)))
+ );
+
+ return {
+ [Symbol.iterator]: function*() {
+ for (const item of values) {
+ yield gripFromEntry(objectActor, item);
+ }
+ },
+ size: values.length,
+ propertyName(index) {
+ return index;
+ },
+ propertyDescription(index) {
+ const val = values[index];
+ return {
+ enumerable: true,
+ value: gripFromEntry(objectActor, val),
+ };
+ },
+ };
+}
+
/**
* Returns true if the parameter can be stored as a 32-bit unsigned integer.
* If so, it will be suitable for use as the length of an array object.
@@ -672,6 +703,7 @@ function isUint32(num) {
module.exports = {
PropertyIteratorActor,
+ enumCustomStateSetEntries,
enumMapEntries,
enumMidiInputMapEntries,
enumMidiOutputMapEntries,
diff --git a/devtools/server/actors/objects-manager.js b/devtools/server/actors/objects-manager.js
index 529b33b246..9338f7c8f6 100644
--- a/devtools/server/actors/objects-manager.js
+++ b/devtools/server/actors/objects-manager.js
@@ -14,7 +14,7 @@ const {
* inspected by DevTools. Typically from the Console or Debugger.
*/
class ObjectsManagerActor extends Actor {
- constructor(conn, targetActor) {
+ constructor(conn) {
super(conn, objectsManagerSpec);
}
diff --git a/devtools/server/actors/page-style.js b/devtools/server/actors/page-style.js
index cfaa35ed46..1783b58a8f 100644
--- a/devtools/server/actors/page-style.js
+++ b/devtools/server/actors/page-style.js
@@ -727,9 +727,13 @@ class PageStyleActor extends Actor {
case "::-moz-range-progress":
case "::-moz-range-thumb":
case "::-moz-range-track":
+ case "::slider-fill":
+ case "::slider-thumb":
+ case "::slider-track":
return node.nodeName == "INPUT" && node.type == "range";
default:
- throw Error("Unhandled pseudo-element " + pseudo);
+ console.error("Unhandled pseudo-element " + pseudo);
+ return false;
}
}
diff --git a/devtools/server/actors/preference.js b/devtools/server/actors/preference.js
index 3435fe9eb1..17a3116d9e 100644
--- a/devtools/server/actors/preference.js
+++ b/devtools/server/actors/preference.js
@@ -57,7 +57,7 @@ class PreferenceActor extends Actor {
getAllPrefs() {
const prefs = {};
- Services.prefs.getChildList("").forEach(function (name, index) {
+ Services.prefs.getChildList("").forEach(function (name) {
// append all key/value pairs into a huge json object.
try {
let value;
diff --git a/devtools/server/actors/reflow.js b/devtools/server/actors/reflow.js
index 3eda67cc8c..6fd3962d75 100644
--- a/devtools/server/actors/reflow.js
+++ b/devtools/server/actors/reflow.js
@@ -162,11 +162,11 @@ class Observable {
}
}
- _startListeners(windows) {
+ _startListeners() {
// To be implemented by sub-classes.
}
- _stopListeners(windows) {
+ _stopListeners() {
// To be implemented by sub-classes.
}
diff --git a/devtools/server/actors/resources/extensions-backgroundscript-status.js b/devtools/server/actors/resources/extensions-backgroundscript-status.js
index 08f51a23f5..f6c7b3067d 100644
--- a/devtools/server/actors/resources/extensions-backgroundscript-status.js
+++ b/devtools/server/actors/resources/extensions-backgroundscript-status.js
@@ -35,7 +35,7 @@ class ExtensionsBackgroundScriptStatusWatcher {
Services.obs.addObserver(this, "extension:background-script-status");
}
- observe(subject, topic, data) {
+ observe(subject, topic) {
switch (topic) {
case "extension:background-script-status": {
const { addonId, isRunning } = subject.wrappedJSObject;
diff --git a/devtools/server/actors/resources/network-events-content.js b/devtools/server/actors/resources/network-events-content.js
index 5135583fab..2b4b09dfa7 100644
--- a/devtools/server/actors/resources/network-events-content.js
+++ b/devtools/server/actors/resources/network-events-content.js
@@ -13,10 +13,14 @@ loader.lazyRequireGetter(
const lazy = {};
-ChromeUtils.defineESModuleGetters(lazy, {
- NetworkUtils:
- "resource://devtools/shared/network-observer/NetworkUtils.sys.mjs",
-});
+ChromeUtils.defineESModuleGetters(
+ lazy,
+ {
+ NetworkUtils:
+ "resource://devtools/shared/network-observer/NetworkUtils.sys.mjs",
+ },
+ { global: "contextual" }
+);
/**
* Handles network events from the content process
@@ -64,7 +68,7 @@ class NetworkEventContentWatcher {
this.networkEvents.clear();
}
- httpFailedOpeningRequest(subject, topic) {
+ httpFailedOpeningRequest(subject) {
const channel = subject.QueryInterface(Ci.nsIHttpChannel);
// Ignore preload requests to avoid duplicity request entries in
diff --git a/devtools/server/actors/resources/network-events-stacktraces.js b/devtools/server/actors/resources/network-events-stacktraces.js
index a458278680..da082069f5 100644
--- a/devtools/server/actors/resources/network-events-stacktraces.js
+++ b/devtools/server/actors/resources/network-events-stacktraces.js
@@ -17,10 +17,14 @@ loader.lazyRequireGetter(
const lazy = {};
-ChromeUtils.defineESModuleGetters(lazy, {
- NetworkUtils:
- "resource://devtools/shared/network-observer/NetworkUtils.sys.mjs",
-});
+ChromeUtils.defineESModuleGetters(
+ lazy,
+ {
+ NetworkUtils:
+ "resource://devtools/shared/network-observer/NetworkUtils.sys.mjs",
+ },
+ { global: "contextual" }
+);
class NetworkEventStackTracesWatcher {
/**
@@ -53,11 +57,8 @@ class NetworkEventStackTracesWatcher {
/**
* Stop watching for network event's strack traces related to a given Target Actor.
- *
- * @param TargetActor targetActor
- * The target actor from which we should stop observing the strack traces
*/
- destroy(targetActor) {
+ destroy() {
this.clear();
Services.obs.removeObserver(this, "http-on-opening-request");
Services.obs.removeObserver(this, "document-on-opening-request");
@@ -65,7 +66,7 @@ class NetworkEventStackTracesWatcher {
ChannelEventSinkFactory.getService().unregisterCollector(this);
}
- onChannelRedirect(oldChannel, newChannel, flags) {
+ onChannelRedirect(oldChannel, newChannel) {
// We can be called with any nsIChannel, but are interested only in HTTP channels
try {
oldChannel.QueryInterface(Ci.nsIHttpChannel);
diff --git a/devtools/server/actors/resources/network-events.js b/devtools/server/actors/resources/network-events.js
index c1440f2c8d..909c16e052 100644
--- a/devtools/server/actors/resources/network-events.js
+++ b/devtools/server/actors/resources/network-events.js
@@ -6,26 +6,29 @@
const { Pool } = require("resource://devtools/shared/protocol/Pool.js");
const { isWindowGlobalPartOfContext } = ChromeUtils.importESModule(
- "resource://devtools/server/actors/watcher/browsing-context-helpers.sys.mjs"
+ "resource://devtools/server/actors/watcher/browsing-context-helpers.sys.mjs",
+ { global: "contextual" }
);
const { WatcherRegistry } = ChromeUtils.importESModule(
"resource://devtools/server/actors/watcher/WatcherRegistry.sys.mjs",
- {
- // WatcherRegistry needs to be a true singleton and loads ActorManagerParent
- // which also has to be a true singleton.
- loadInDevToolsLoader: false,
- }
+ // WatcherRegistry needs to be a true singleton and loads ActorManagerParent
+ // which also has to be a true singleton.
+ { global: "shared" }
);
const Targets = require("resource://devtools/server/actors/targets/index.js");
const lazy = {};
-ChromeUtils.defineESModuleGetters(lazy, {
- NetworkObserver:
- "resource://devtools/shared/network-observer/NetworkObserver.sys.mjs",
- NetworkUtils:
- "resource://devtools/shared/network-observer/NetworkUtils.sys.mjs",
-});
+ChromeUtils.defineESModuleGetters(
+ lazy,
+ {
+ NetworkObserver:
+ "resource://devtools/shared/network-observer/NetworkObserver.sys.mjs",
+ NetworkUtils:
+ "resource://devtools/shared/network-observer/NetworkUtils.sys.mjs",
+ },
+ { global: "contextual" }
+);
loader.lazyRequireGetter(
this,
diff --git a/devtools/server/actors/resources/parent-process-document-event.js b/devtools/server/actors/resources/parent-process-document-event.js
index e156a32fe5..27f929190c 100644
--- a/devtools/server/actors/resources/parent-process-document-event.js
+++ b/devtools/server/actors/resources/parent-process-document-event.js
@@ -98,7 +98,7 @@ class ParentProcessDocumentEventWatcher {
return Promise.resolve();
}
- onStateChange(progress, request, flag, status) {
+ onStateChange(progress, request, flag) {
const isStart = flag & Ci.nsIWebProgressListener.STATE_START;
const isDocument = flag & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
if (isDocument && isStart) {
diff --git a/devtools/server/actors/resources/server-sent-events.js b/devtools/server/actors/resources/server-sent-events.js
index 5b16f8bb9f..894bbc76bc 100644
--- a/devtools/server/actors/resources/server-sent-events.js
+++ b/devtools/server/actors/resources/server-sent-events.js
@@ -102,7 +102,7 @@ class ServerSentEventWatcher {
}
// nsIEventSourceEventService specific functions
- eventSourceConnectionOpened(httpChannelId) {}
+ eventSourceConnectionOpened() {}
eventSourceConnectionClosed(httpChannelId) {
const resource = ServerSentEventWatcher.createResource(
diff --git a/devtools/server/actors/resources/sources.js b/devtools/server/actors/resources/sources.js
index 6b3ab1d5e1..c4f0601106 100644
--- a/devtools/server/actors/resources/sources.js
+++ b/devtools/server/actors/resources/sources.js
@@ -69,13 +69,13 @@ class SourceWatcher {
// Before fetching all sources, process existing ones.
// The ThreadActor is already up and running before this code runs
// and have sources already registered and for which newSource event already fired.
- onAvailable(
- threadActor.sourcesManager.iter().map(s => {
- const resource = s.form();
- resource.resourceType = SOURCE;
- return resource;
- })
- );
+ const sources = [];
+ for (const sourceActor of threadActor.sourcesManager.iter()) {
+ const resource = sourceActor.form();
+ resource.resourceType = SOURCE;
+ sources.push(resource);
+ }
+ onAvailable(sources);
// Requesting all sources should end up emitting newSource on threadActor.sourcesManager
threadActor.addAllSources();
diff --git a/devtools/server/actors/resources/storage/extension-storage.js b/devtools/server/actors/resources/storage/extension-storage.js
index d14d3320c7..be98c917b3 100644
--- a/devtools/server/actors/resources/storage/extension-storage.js
+++ b/devtools/server/actors/resources/storage/extension-storage.js
@@ -13,25 +13,25 @@ const {
const {
LongStringActor,
} = require("resource://devtools/server/actors/string.js");
-// Use loadInDevToolsLoader: false for these extension modules, because these
+// Use global: "shared" for these extension modules, because these
// are singletons with shared state, and we must not create a new instance if a
// dedicated loader was used to load this module.
loader.lazyGetter(this, "ExtensionParent", () => {
return ChromeUtils.importESModule(
"resource://gre/modules/ExtensionParent.sys.mjs",
- { loadInDevToolsLoader: false }
+ { global: "shared" }
).ExtensionParent;
});
loader.lazyGetter(this, "ExtensionProcessScript", () => {
return ChromeUtils.importESModule(
"resource://gre/modules/ExtensionProcessScript.sys.mjs",
- { loadInDevToolsLoader: false }
+ { global: "shared" }
).ExtensionProcessScript;
});
loader.lazyGetter(this, "ExtensionStorageIDB", () => {
return ChromeUtils.importESModule(
"resource://gre/modules/ExtensionStorageIDB.sys.mjs",
- { loadInDevToolsLoader: false }
+ { global: "shared" }
).ExtensionStorageIDB;
});
@@ -310,7 +310,7 @@ class ExtensionStorageActor extends BaseStorageActor {
});
}
- async editItem({ host, field, items, oldValue }) {
+ async editItem({ host, items }) {
const db = this.dbConnectionForHost.get(host);
if (!db) {
return;
diff --git a/devtools/server/actors/resources/storage/indexed-db.js b/devtools/server/actors/resources/storage/indexed-db.js
index 8ded705c4f..05c523ac57 100644
--- a/devtools/server/actors/resources/storage/indexed-db.js
+++ b/devtools/server/actors/resources/storage/indexed-db.js
@@ -30,9 +30,13 @@ loader.lazyGetter(this, "indexedDBForStorage", () => {
}
});
const lazy = {};
-ChromeUtils.defineESModuleGetters(lazy, {
- Sqlite: "resource://gre/modules/Sqlite.sys.mjs",
-});
+ChromeUtils.defineESModuleGetters(
+ lazy,
+ {
+ Sqlite: "resource://gre/modules/Sqlite.sys.mjs",
+ },
+ { global: "contextual" }
+);
/**
* An async method equivalent to setTimeout but using Promises
@@ -882,7 +886,7 @@ class IndexedDBStorageActor extends BaseStorageActor {
const { name } = this.splitNameAndStorage(dbName);
const request = this.openWithPrincipal(principal, name, storage);
- return new Promise((resolve, reject) => {
+ return new Promise(resolve => {
let { objectStore, id, index, offset, size } = requestOptions;
const data = [];
let db;
diff --git a/devtools/server/actors/resources/thread-states.js b/devtools/server/actors/resources/thread-states.js
index 9ac79088d2..11aef81734 100644
--- a/devtools/server/actors/resources/thread-states.js
+++ b/devtools/server/actors/resources/thread-states.js
@@ -7,6 +7,7 @@
const {
TYPES: { THREAD_STATE },
} = require("resource://devtools/server/actors/resources/index.js");
+const Targets = require("resource://devtools/server/actors/targets/index.js");
const {
PAUSE_REASONS,
@@ -48,6 +49,18 @@ class BreakpointWatcher {
* This will be called for each resource.
*/
async watch(targetActor, { onAvailable }) {
+ // When debugging the whole browser (via the Browser Toolbox), we instantiate both content process and window global (FRAME) targets.
+ // But the debugger will only use the content process target's thread actor.
+ // Thread actor, Sources and Breakpoints have to be only managed for the content process target,
+ // and we should explicitly ignore the window global target.
+ if (
+ targetActor.sessionContext.type == "all" &&
+ targetActor.targetType === Targets.TYPES.FRAME &&
+ targetActor.typeName != "parentProcessTarget"
+ ) {
+ return;
+ }
+
const { threadActor } = targetActor;
this.threadActor = threadActor;
this.onAvailable = onAvailable;
@@ -87,6 +100,9 @@ class BreakpointWatcher {
* Stop watching for breakpoints
*/
destroy() {
+ if (!this.threadActor) {
+ return;
+ }
this.threadActor.off("paused", this.onPaused);
this.threadActor.off("resumed", this.onResumed);
}
@@ -116,7 +132,7 @@ class BreakpointWatcher {
]);
}
- onResumed(packet) {
+ onResumed() {
// NOTE: resumed events are suppressed while interrupted
// to prevent unintentional behavior.
if (this.isInterrupted) {
diff --git a/devtools/server/actors/resources/utils/content-process-storage.js b/devtools/server/actors/resources/utils/content-process-storage.js
index 7e126ce3f7..80d7e319a8 100644
--- a/devtools/server/actors/resources/utils/content-process-storage.js
+++ b/devtools/server/actors/resources/utils/content-process-storage.js
@@ -7,10 +7,14 @@
const EventEmitter = require("resource://devtools/shared/event-emitter.js");
const lazy = {};
-ChromeUtils.defineESModuleGetters(lazy, {
- getAddonIdForWindowGlobal:
- "resource://devtools/server/actors/watcher/browsing-context-helpers.sys.mjs",
-});
+ChromeUtils.defineESModuleGetters(
+ lazy,
+ {
+ getAddonIdForWindowGlobal:
+ "resource://devtools/server/actors/watcher/browsing-context-helpers.sys.mjs",
+ },
+ { global: "contextual" }
+);
// ms of delay to throttle updates
const BATCH_DELAY = 200;
diff --git a/devtools/server/actors/resources/utils/nsi-console-listener-watcher.js b/devtools/server/actors/resources/utils/nsi-console-listener-watcher.js
index 8d1ed43612..d4bde43818 100644
--- a/devtools/server/actors/resources/utils/nsi-console-listener-watcher.js
+++ b/devtools/server/actors/resources/utils/nsi-console-listener-watcher.js
@@ -79,7 +79,7 @@ class nsIConsoleListenerWatcher {
* @param {TargetActor} targetActor
* @return {Boolean}
*/
- shouldHandleTarget(targetActor) {
+ shouldHandleTarget() {
return true;
}
@@ -91,7 +91,7 @@ class nsIConsoleListenerWatcher {
* @param {nsIScriptError|nsIConsoleMessage} message
* @return {Boolean}
*/
- shouldHandleMessage(targetActor, message) {
+ shouldHandleMessage() {
throw new Error(
"'shouldHandleMessage' should be implemented in the class that extends nsIConsoleListenerWatcher"
);
@@ -101,12 +101,12 @@ class nsIConsoleListenerWatcher {
* Prepare the resource to be sent to the client. This should be implemented on the
* child class.
*
- * @param targetActor
- * @param nsIScriptError|nsIConsoleMessage message
+ * @param _targetActor
+ * @param nsIScriptError|nsIConsoleMessage _message
* @return object
* The object you can send to the remote client.
*/
- buildResource(targetActor, message) {
+ buildResource(_targetActor, _message) {
throw new Error(
"'buildResource' should be implemented in the class that extends nsIConsoleListenerWatcher"
);
diff --git a/devtools/server/actors/resources/utils/parent-process-storage.js b/devtools/server/actors/resources/utils/parent-process-storage.js
index 423d13b6b5..760e6e4d38 100644
--- a/devtools/server/actors/resources/utils/parent-process-storage.js
+++ b/devtools/server/actors/resources/utils/parent-process-storage.js
@@ -6,7 +6,8 @@
const EventEmitter = require("resource://devtools/shared/event-emitter.js");
const { isWindowGlobalPartOfContext } = ChromeUtils.importESModule(
- "resource://devtools/server/actors/watcher/browsing-context-helpers.sys.mjs"
+ "resource://devtools/server/actors/watcher/browsing-context-helpers.sys.mjs",
+ { global: "contextual" }
);
// ms of delay to throttle updates
diff --git a/devtools/server/actors/resources/websockets.js b/devtools/server/actors/resources/websockets.js
index 5845357a9c..58507f9fbb 100644
--- a/devtools/server/actors/resources/websockets.js
+++ b/devtools/server/actors/resources/websockets.js
@@ -97,7 +97,7 @@ class WebSocketWatcher {
}
// methods for the nsIWebSocketEventService
- webSocketCreated(webSocketSerialID, uri, protocols) {}
+ webSocketCreated() {}
webSocketOpened(
webSocketSerialID,
@@ -117,7 +117,7 @@ class WebSocketWatcher {
this.onAvailable([resource]);
}
- webSocketMessageAvailable(webSocketSerialID, data, messageType) {}
+ webSocketMessageAvailable() {}
webSocketClosed(webSocketSerialID, wasClean, code, reason) {
const httpChannelId = this.connections.get(webSocketSerialID);
diff --git a/devtools/server/actors/root.js b/devtools/server/actors/root.js
index df16c70b2f..90836d524e 100644
--- a/devtools/server/actors/root.js
+++ b/devtools/server/actors/root.js
@@ -135,8 +135,6 @@ class RootActor extends Actor {
"dom.worker.console.dispatch_events_to_main_thread"
)
: true,
- // @backward-compat { version 123 } A new Objects Manager front has a new "releaseActors" method.
- supportsReleaseActors: true,
};
}
diff --git a/devtools/server/actors/source.js b/devtools/server/actors/source.js
index ff08bcb4c2..e246e11b8c 100644
--- a/devtools/server/actors/source.js
+++ b/devtools/server/actors/source.js
@@ -128,7 +128,7 @@ class SourceActor extends Actor {
// because we can't easily fetch the full html content of the srcdoc attribute.
this.__isInlineSource =
source.introductionType === "inlineScript" &&
- !resolveSourceURL(source.displayURL, this.threadActor._parent) &&
+ !resolveSourceURL(source.displayURL, this.threadActor.targetActor) &&
!this.url.startsWith("about:srcdoc");
}
return this.__isInlineSource;
@@ -148,7 +148,7 @@ class SourceActor extends Actor {
}
get url() {
if (this._url === undefined) {
- this._url = getSourceURL(this._source, this.threadActor._parent);
+ this._url = getSourceURL(this._source, this.threadActor.targetActor);
}
return this._url;
}
@@ -205,7 +205,7 @@ class SourceActor extends Actor {
isBlackBoxed: this.sourcesManager.isBlackBoxed(this.url),
sourceMapBaseURL: getSourcemapBaseURL(
this.url,
- this.threadActor._parent.window
+ this.threadActor.targetActor.window
),
sourceMapURL: source.sourceMapURL,
introductionType,
diff --git a/devtools/server/actors/target-configuration.js b/devtools/server/actors/target-configuration.js
index 35340ee668..b6db235143 100644
--- a/devtools/server/actors/target-configuration.js
+++ b/devtools/server/actors/target-configuration.js
@@ -13,7 +13,8 @@ const {
SessionDataHelpers,
} = require("resource://devtools/server/actors/watcher/SessionDataHelpers.jsm");
const { isBrowsingContextPartOfContext } = ChromeUtils.importESModule(
- "resource://devtools/server/actors/watcher/browsing-context-helpers.sys.mjs"
+ "resource://devtools/server/actors/watcher/browsing-context-helpers.sys.mjs",
+ { global: "contextual" }
);
const { SUPPORTED_DATA } = SessionDataHelpers;
const { TARGET_CONFIGURATION } = SUPPORTED_DATA;
diff --git a/devtools/server/actors/targets/content-process.js b/devtools/server/actors/targets/content-process.js
index 56b1934ef1..cb6c34cea6 100644
--- a/devtools/server/actors/targets/content-process.js
+++ b/devtools/server/actors/targets/content-process.js
@@ -31,9 +31,7 @@ const {
} = require("resource://devtools/server/actors/targets/base-target-actor.js");
const { TargetActorRegistry } = ChromeUtils.importESModule(
"resource://devtools/server/actors/targets/target-actor-registry.sys.mjs",
- {
- loadInDevToolsLoader: false,
- }
+ { global: "shared" }
);
loader.lazyRequireGetter(
@@ -67,7 +65,7 @@ class ContentProcessTargetActor extends BaseTargetActor {
this.makeDebugger = makeDebugger.bind(null, {
findDebuggees: dbg =>
dbg.findAllGlobals().map(g => g.unsafeDereference()),
- shouldAddNewGlobalAsDebuggee: global => true,
+ shouldAddNewGlobalAsDebuggee: () => true,
});
const sandboxPrototype = {
@@ -149,7 +147,7 @@ class ContentProcessTargetActor extends BaseTargetActor {
}
if (!this.threadActor) {
- this.threadActor = new ThreadActor(this, null);
+ this.threadActor = new ThreadActor(this);
this.manage(this.threadActor);
}
if (!this.memoryActor) {
@@ -218,7 +216,7 @@ class ContentProcessTargetActor extends BaseTargetActor {
this.ensureWorkerList().workerPauser.setPauseServiceWorkers(request.origin);
}
- destroy() {
+ destroy({ isModeSwitching } = {}) {
// Avoid reentrancy. We will destroy the Transport when emitting "destroyed",
// which will force destroying all actors.
if (this.destroying) {
@@ -230,7 +228,7 @@ class ContentProcessTargetActor extends BaseTargetActor {
// otherwise you might have leaks reported when running browser_browser_toolbox_netmonitor.js in debug builds
Resources.unwatchAllResources(this);
- this.emit("destroyed");
+ this.emit("destroyed", { isModeSwitching });
super.destroy();
diff --git a/devtools/server/actors/targets/session-data-processors/blackboxing.js b/devtools/server/actors/targets/session-data-processors/blackboxing.js
index 70f4397a72..92bfa74569 100644
--- a/devtools/server/actors/targets/session-data-processors/blackboxing.js
+++ b/devtools/server/actors/targets/session-data-processors/blackboxing.js
@@ -20,7 +20,7 @@ module.exports = {
}
},
- removeSessionDataEntry(targetActor, entries, isDocumentCreation) {
+ removeSessionDataEntry(targetActor, entries) {
for (const { url, range } of entries) {
targetActor.sourcesManager.unblackBox(url, range);
}
diff --git a/devtools/server/actors/targets/session-data-processors/breakpoints.js b/devtools/server/actors/targets/session-data-processors/breakpoints.js
index ff7cb7ec0a..67c270654d 100644
--- a/devtools/server/actors/targets/session-data-processors/breakpoints.js
+++ b/devtools/server/actors/targets/session-data-processors/breakpoints.js
@@ -7,6 +7,7 @@
const {
STATES: THREAD_STATES,
} = require("resource://devtools/server/actors/thread.js");
+const Targets = require("resource://devtools/server/actors/targets/index.js");
module.exports = {
async addOrSetSessionDataEntry(
@@ -15,6 +16,17 @@ module.exports = {
isDocumentCreation,
updateType
) {
+ // When debugging the whole browser (via the Browser Toolbox), we instantiate both content process and window global (FRAME) targets.
+ // But the debugger will only use the content process target's thread actor.
+ // Thread actor, Sources and Breakpoints have to be only managed for the content process target,
+ // and we should explicitly ignore the window global target.
+ if (
+ targetActor.sessionContext.type == "all" &&
+ targetActor.targetType === Targets.TYPES.FRAME &&
+ targetActor.typeName != "parentProcessTarget"
+ ) {
+ return;
+ }
const { threadActor } = targetActor;
if (updateType == "set") {
threadActor.removeAllBreakpoints();
@@ -37,7 +49,7 @@ module.exports = {
}
},
- removeSessionDataEntry(targetActor, entries, isDocumentCreation) {
+ removeSessionDataEntry(targetActor, entries) {
for (const { location } of entries) {
targetActor.threadActor.removeBreakpoint(location);
}
diff --git a/devtools/server/actors/targets/session-data-processors/event-breakpoints.js b/devtools/server/actors/targets/session-data-processors/event-breakpoints.js
index c0a2fb7ffe..4eb9e4f3a8 100644
--- a/devtools/server/actors/targets/session-data-processors/event-breakpoints.js
+++ b/devtools/server/actors/targets/session-data-processors/event-breakpoints.js
@@ -30,7 +30,7 @@ module.exports = {
}
},
- removeSessionDataEntry(targetActor, entries, isDocumentCreation) {
+ removeSessionDataEntry(targetActor, entries) {
targetActor.threadActor.removeEventBreakpoints(entries);
},
};
diff --git a/devtools/server/actors/targets/session-data-processors/resources.js b/devtools/server/actors/targets/session-data-processors/resources.js
index 8f33ba8e0f..1e08397256 100644
--- a/devtools/server/actors/targets/session-data-processors/resources.js
+++ b/devtools/server/actors/targets/session-data-processors/resources.js
@@ -19,7 +19,7 @@ module.exports = {
await Resources.watchResources(targetActor, entries);
},
- removeSessionDataEntry(targetActor, entries, isDocumentCreation) {
+ removeSessionDataEntry(targetActor, entries) {
Resources.unwatchResources(targetActor, entries);
},
};
diff --git a/devtools/server/actors/targets/session-data-processors/target-configuration.js b/devtools/server/actors/targets/session-data-processors/target-configuration.js
index f68e82d69f..8f10692178 100644
--- a/devtools/server/actors/targets/session-data-processors/target-configuration.js
+++ b/devtools/server/actors/targets/session-data-processors/target-configuration.js
@@ -5,12 +5,7 @@
"use strict";
module.exports = {
- async addOrSetSessionDataEntry(
- targetActor,
- entries,
- isDocumentCreation,
- updateType
- ) {
+ async addOrSetSessionDataEntry(targetActor, entries, isDocumentCreation) {
// Only WindowGlobalTargetActor implements updateTargetConfiguration,
// skip targetActor data entry update for other targets.
if (typeof targetActor.updateTargetConfiguration == "function") {
@@ -26,7 +21,7 @@ module.exports = {
}
},
- removeSessionDataEntry(targetActor, entries, isDocumentCreation) {
+ removeSessionDataEntry() {
// configuration data entries are always added/updated, never removed.
},
};
diff --git a/devtools/server/actors/targets/session-data-processors/thread-configuration.js b/devtools/server/actors/targets/session-data-processors/thread-configuration.js
index 716d2a9b21..ad5c0fe024 100644
--- a/devtools/server/actors/targets/session-data-processors/thread-configuration.js
+++ b/devtools/server/actors/targets/session-data-processors/thread-configuration.js
@@ -7,14 +7,21 @@
const {
STATES: THREAD_STATES,
} = require("resource://devtools/server/actors/thread.js");
+const Targets = require("resource://devtools/server/actors/targets/index.js");
module.exports = {
- async addOrSetSessionDataEntry(
- targetActor,
- entries,
- isDocumentCreation,
- updateType
- ) {
+ async addOrSetSessionDataEntry(targetActor, entries) {
+ // When debugging the whole browser (via the Browser Toolbox), we instantiate both content process and window global (FRAME) targets.
+ // But the debugger will only use the content process target's thread actor.
+ // Thread actor, Sources and Breakpoints have to be only managed for the content process target,
+ // and we should explicitly ignore the window global target.
+ if (
+ targetActor.sessionContext.type == "all" &&
+ targetActor.targetType === Targets.TYPES.FRAME &&
+ targetActor.typeName != "parentProcessTarget"
+ ) {
+ return;
+ }
const threadOptions = {};
for (const { key, value } of entries) {
@@ -35,7 +42,7 @@ module.exports = {
}
},
- removeSessionDataEntry(targetActor, entries, isDocumentCreation) {
+ removeSessionDataEntry() {
// configuration data entries are always added/updated, never removed.
},
};
diff --git a/devtools/server/actors/targets/session-data-processors/xhr-breakpoints.js b/devtools/server/actors/targets/session-data-processors/xhr-breakpoints.js
index 7a0fd815aa..3bbcf54aaf 100644
--- a/devtools/server/actors/targets/session-data-processors/xhr-breakpoints.js
+++ b/devtools/server/actors/targets/session-data-processors/xhr-breakpoints.js
@@ -36,7 +36,7 @@ module.exports = {
);
},
- removeSessionDataEntry(targetActor, entries, isDocumentCreation) {
+ removeSessionDataEntry(targetActor, entries) {
for (const { path, method } of entries) {
targetActor.threadActor.removeXHRBreakpoint(path, method);
}
diff --git a/devtools/server/actors/targets/target-actor-registry.sys.mjs b/devtools/server/actors/targets/target-actor-registry.sys.mjs
index 4cb6d13868..25c1ac1234 100644
--- a/devtools/server/actors/targets/target-actor-registry.sys.mjs
+++ b/devtools/server/actors/targets/target-actor-registry.sys.mjs
@@ -24,7 +24,7 @@ export var TargetActorRegistry = {
xpcShellTargetActor = targetActor;
},
- unregisterXpcShellTargetActor(targetActor) {
+ unregisterXpcShellTargetActor() {
xpcShellTargetActor = null;
},
diff --git a/devtools/server/actors/targets/window-global.js b/devtools/server/actors/targets/window-global.js
index 5d2bb10164..6719f0518d 100644
--- a/devtools/server/actors/targets/window-global.js
+++ b/devtools/server/actors/targets/window-global.js
@@ -33,12 +33,11 @@ var makeDebugger = require("resource://devtools/server/actors/utils/make-debugge
const Targets = require("resource://devtools/server/actors/targets/index.js");
const { TargetActorRegistry } = ChromeUtils.importESModule(
"resource://devtools/server/actors/targets/target-actor-registry.sys.mjs",
- {
- loadInDevToolsLoader: false,
- }
+ { global: "shared" }
);
const { PrivateBrowsingUtils } = ChromeUtils.importESModule(
- "resource://gre/modules/PrivateBrowsingUtils.sys.mjs"
+ "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
+ { global: "contextual" }
);
const EXTENSION_CONTENT_SYS_MJS =
@@ -82,7 +81,7 @@ loader.lazyGetter(lazy, "ExtensionContent", () => {
// main loader. Note that the user of lazy.ExtensionContent elsewhere in
// this file (at webextensionsContentScriptGlobals) looks up the module
// via Cu.isESModuleLoaded, which also uses the main loader as desired.
- loadInDevToolsLoader: false,
+ global: "shared",
}).ExtensionContent;
});
@@ -888,7 +887,7 @@ class WindowGlobalTargetActor extends BaseTargetActor {
return {};
}
- listFrames(request) {
+ listFrames() {
const windows = this._docShellsToWindows(this.docShells);
return { frames: windows };
}
@@ -912,7 +911,7 @@ class WindowGlobalTargetActor extends BaseTargetActor {
);
}
- listWorkers(request) {
+ listWorkers() {
return this.ensureWorkerDescriptorActorList()
.getList()
.then(actors => {
@@ -960,7 +959,7 @@ class WindowGlobalTargetActor extends BaseTargetActor {
this.emit("workerListChanged");
}
- _onConsoleApiProfilerEvent(subject, topic, data) {
+ _onConsoleApiProfilerEvent() {
// TODO: We will receive console-api-profiler events for any browser running
// in the same process as this target. We should filter irrelevant events,
// but console-api-profiler currently doesn't emit any information to identify
@@ -977,7 +976,7 @@ class WindowGlobalTargetActor extends BaseTargetActor {
});
}
- observe(subject, topic, data) {
+ observe(subject, topic) {
// Ignore any event that comes before/after the actor is attached.
// That typically happens during Firefox shutdown.
if (this.isDestroyed()) {
@@ -1165,7 +1164,7 @@ class WindowGlobalTargetActor extends BaseTargetActor {
* This sets up the content window for being debugged
*/
_createThreadActor() {
- this.threadActor = new ThreadActor(this, this.window);
+ this.threadActor = new ThreadActor(this);
this.manage(this.threadActor);
}
@@ -1187,7 +1186,7 @@ class WindowGlobalTargetActor extends BaseTargetActor {
// Protocol Request Handlers
- detach(request) {
+ detach() {
// Destroy the actor in the next event loop in order
// to ensure responding to the `detach` request.
DevToolsUtils.executeSoon(() => {
@@ -1824,7 +1823,7 @@ class DebuggerProgressListener {
this._knownWindowIDs.delete(getWindowID(window));
}, "DebuggerProgressListener.prototype.onWindowHidden");
- observe = DevToolsUtils.makeInfallible(function (subject, topic) {
+ observe = DevToolsUtils.makeInfallible(function (subject) {
if (this._targetActor.isDestroyed()) {
return;
}
@@ -1859,8 +1858,7 @@ class DebuggerProgressListener {
onStateChange = DevToolsUtils.makeInfallible(function (
progress,
request,
- flag,
- status
+ flag
) {
if (this._targetActor.isDestroyed()) {
return;
diff --git a/devtools/server/actors/targets/worker.js b/devtools/server/actors/targets/worker.js
index cf5f7b83c9..20b60cfa24 100644
--- a/devtools/server/actors/targets/worker.js
+++ b/devtools/server/actors/targets/worker.js
@@ -72,7 +72,7 @@ class WorkerTargetActor extends BaseTargetActor {
});
// needed by the console actor
- this.threadActor = new ThreadActor(this, this.workerGlobal);
+ this.threadActor = new ThreadActor(this);
// needed by the thread actor to communicate with the console when evaluating logpoints.
this._consoleActor = new WebConsoleActor(this.conn, this);
diff --git a/devtools/server/actors/thread-configuration.js b/devtools/server/actors/thread-configuration.js
index 8cd28f5887..f0c697bb51 100644
--- a/devtools/server/actors/thread-configuration.js
+++ b/devtools/server/actors/thread-configuration.js
@@ -17,29 +17,33 @@ const {
} = SessionDataHelpers;
// List of options supported by this thread configuration actor.
+/* eslint sort-keys: "error" */
const SUPPORTED_OPTIONS = {
- // Controls pausing on debugger statement.
- // (This is enabled by default if omitted)
- shouldPauseOnDebuggerStatement: true,
- // Enable pausing on exceptions.
- pauseOnExceptions: true,
// Disable pausing on caught exceptions.
ignoreCaughtExceptions: true,
- // Include previously saved stack frames when paused.
- shouldIncludeSavedFrames: true,
- // Include async stack frames when paused.
- shouldIncludeAsyncLiveFrames: true,
- // Stop pausing on breakpoints.
- skipBreakpoints: true,
// Log the event break points.
logEventBreakpoints: true,
// Enable debugging asm & wasm.
// See https://searchfox.org/mozilla-central/source/js/src/doc/Debugger/Debugger.md#16-26
observeAsmJS: true,
observeWasm: true,
+ // Enable pausing on exceptions.
+ pauseOnExceptions: true,
+ // Boolean to know if we should display the overlay when pausing
+ pauseOverlay: true,
// Should pause all the workers untill thread has attached.
pauseWorkersUntilAttach: true,
+ // Include async stack frames when paused.
+ shouldIncludeAsyncLiveFrames: true,
+ // Include previously saved stack frames when paused.
+ shouldIncludeSavedFrames: true,
+ // Controls pausing on debugger statement.
+ // (This is enabled by default if omitted)
+ shouldPauseOnDebuggerStatement: true,
+ // Stop pausing on breakpoints.
+ skipBreakpoints: true,
};
+/* eslint-disable sort-keys */
/**
* This actor manages the configuration options which apply to thread actor for all the targets.
diff --git a/devtools/server/actors/thread.js b/devtools/server/actors/thread.js
index d33b3e5eb2..07dcc27a6a 100644
--- a/devtools/server/actors/thread.js
+++ b/devtools/server/actors/thread.js
@@ -32,6 +32,7 @@ const {
const {
logEvent,
} = require("resource://devtools/server/actors/utils/logEvent.js");
+const Targets = require("devtools/server/actors/targets/index");
loader.lazyRequireGetter(
this,
@@ -169,24 +170,23 @@ class ThreadActor extends Actor {
*
* ThreadActors manage execution/inspection of debuggees.
*
- * @param parent TargetActor
- * This |ThreadActor|'s parent actor. i.e. one of the many Target actors.
- * @param aGlobal object [optional]
- * An optional (for content debugging only) reference to the content
- * window.
+ * @param {TargetActor} targetActor
+ * This `ThreadActor`'s parent actor. i.e. one of the many Target actors.
*/
- constructor(parent, global) {
- super(parent.conn, threadSpec);
+ constructor(targetActor) {
+ super(targetActor.conn, threadSpec);
+
+ // This attribute is used by various other actors to find the target actor
+ this.targetActor = targetActor;
this._state = STATES.DETACHED;
- this._parent = parent;
- this.global = global;
this._options = {
skipBreakpoints: false,
};
this._gripDepth = 0;
- this._parentClosed = false;
+ this._targetActorClosed = false;
this._observingNetwork = false;
+ this._shouldShowPauseOverlay = true;
this._frameActors = [];
this._xhrBreakpoints = [];
@@ -233,9 +233,9 @@ class ThreadActor extends Actor {
this._onWillNavigate = this._onWillNavigate.bind(this);
this._onNavigate = this._onNavigate.bind(this);
- this._parent.on("window-ready", this._onWindowReady);
- this._parent.on("will-navigate", this._onWillNavigate);
- this._parent.on("navigate", this._onNavigate);
+ this.targetActor.on("window-ready", this._onWindowReady);
+ this.targetActor.on("will-navigate", this._onWillNavigate);
+ this.targetActor.on("navigate", this._onNavigate);
this._firstStatementBreakpoint = null;
this._debuggerNotificationObserver = new DebuggerNotificationObserver();
@@ -246,7 +246,7 @@ class ThreadActor extends Actor {
get dbg() {
if (!this._dbg) {
- this._dbg = this._parent.dbg;
+ this._dbg = this.targetActor.dbg;
// Keep the debugger disabled until a client attaches.
if (this._state === STATES.DETACHED) {
this._dbg.disable();
@@ -289,11 +289,11 @@ class ThreadActor extends Actor {
}
get sourcesManager() {
- return this._parent.sourcesManager;
+ return this.targetActor.sourcesManager;
}
get breakpoints() {
- return this._parent.breakpoints;
+ return this.targetActor.breakpoints;
}
get youngestFrame() {
@@ -360,9 +360,9 @@ class ThreadActor extends Actor {
} catch (e) {}
}
- this._parent.off("window-ready", this._onWindowReady);
- this._parent.off("will-navigate", this._onWillNavigate);
- this._parent.off("navigate", this._onNavigate);
+ this.targetActor.off("window-ready", this._onWindowReady);
+ this.targetActor.off("will-navigate", this._onWillNavigate);
+ this.targetActor.off("navigate", this._onNavigate);
this.sourcesManager.off("newSource", this.onNewSourceEvent);
this.clearDebuggees();
@@ -418,11 +418,11 @@ class ThreadActor extends Actor {
this.alreadyAttached = true;
this.dbg.enable();
- // Notify the parent that we've finished attaching. If this is a worker
+ // Notify the target actor that we've finished attaching. If this is a worker
// thread which was paused until attaching, this will allow content to
// begin executing.
- if (this._parent.onThreadAttached) {
- this._parent.onThreadAttached();
+ if (this.targetActor.onThreadAttached) {
+ this.targetActor.onThreadAttached();
}
if (Services.obs) {
// Set a wrappedJSObject property so |this| can be sent via the observer service
@@ -443,7 +443,7 @@ class ThreadActor extends Actor {
}
const env = new HighlighterEnvironment();
- env.initFromTargetActor(this._parent);
+ env.initFromTargetActor(this.targetActor);
const highlighter = new PausedDebuggerOverlay(env, {
resume: () => this.resume(null),
stepOver: () => this.resume({ type: "next" }),
@@ -453,7 +453,13 @@ class ThreadActor extends Actor {
}
_canShowOverlay() {
- const { window } = this._parent;
+ // Only attempt to show on overlay on WindowGlobal targets, which displays a document.
+ // Workers and content processes can't display any overlay.
+ if (this.targetActor.targetType != Targets.TYPES.FRAME) {
+ return false;
+ }
+
+ const { window } = this.targetActor;
// The CanvasFrameAnonymousContentHelper class we're using to create the paused overlay
// need to have access to a documentElement.
@@ -473,21 +479,22 @@ class ThreadActor extends Actor {
async showOverlay() {
if (
- this.isPaused() &&
- this._canShowOverlay() &&
- this._parent.on &&
- this.pauseOverlay
+ !this._shouldShowPauseOverlay ||
+ !this.isPaused() ||
+ !this._canShowOverlay()
) {
- const reason = this._priorPause.why.type;
- await this.pauseOverlay.isReady;
+ return;
+ }
- // we might not be paused anymore.
- if (!this.isPaused()) {
- return;
- }
+ const reason = this._priorPause.why.type;
+ await this.pauseOverlay.isReady;
- this.pauseOverlay.show(reason);
+ // we might not be paused anymore.
+ if (!this.isPaused()) {
+ return;
}
+
+ this.pauseOverlay.show(reason);
}
hideOverlay() {
@@ -590,7 +597,7 @@ class ThreadActor extends Actor {
}
getAvailableEventBreakpoints() {
- return getAvailableEventBreakpoints(this._parent.window);
+ return getAvailableEventBreakpoints(this.targetActor.window);
}
getActiveEventBreakpoints() {
return Array.from(this._activeEventBreakpoints);
@@ -805,12 +812,15 @@ class ThreadActor extends Actor {
if ("observeWasm" in options) {
this.dbg.allowUnobservedWasm = !options.observeWasm;
}
+ if ("pauseOverlay" in options) {
+ this._shouldShowPauseOverlay = !!options.pauseOverlay;
+ }
if (
"pauseWorkersUntilAttach" in options &&
- this._parent.pauseWorkersUntilAttach
+ this.targetActor.pauseWorkersUntilAttach
) {
- this._parent.pauseWorkersUntilAttach(options.pauseWorkersUntilAttach);
+ this.targetActor.pauseWorkersUntilAttach(options.pauseWorkersUntilAttach);
}
if (options.breakpoints) {
@@ -977,10 +987,10 @@ class ThreadActor extends Actor {
// If the parent actor has been closed, terminate the debuggee script
// instead of continuing. Executing JS after the content window is gone is
// a bad idea.
- return this._parentClosed ? null : undefined;
+ return this._targetActorClosed ? null : undefined;
}
- _makeOnEnterFrame({ pauseAndRespond }) {
+ _makeOnEnterFrame() {
return frame => {
if (this._requestedFrameRestart) {
return null;
@@ -1089,7 +1099,7 @@ class ThreadActor extends Actor {
return line !== newLocation.line || column !== newLocation.column;
}
- _makeOnStep({ pauseAndRespond, startFrame, steppingType, completion }) {
+ _makeOnStep({ pauseAndRespond, startFrame, completion }) {
const thread = this;
return function () {
if (thread._validFrameStepOffset(this, startFrame, this.offset)) {
@@ -1336,7 +1346,7 @@ class ThreadActor extends Actor {
* when we do not want to notify the front end of a resume, for example when
* we are shutting down.
*/
- doResume({ resumeLimit } = {}) {
+ doResume() {
this._state = STATES.RUNNING;
// Drop the actors in the pause actor pool.
@@ -1520,7 +1530,7 @@ class ThreadActor extends Actor {
}
}
- sources(request) {
+ sources() {
this.addAllSources();
// No need to flush the new source packets here, as we are sending the
@@ -1528,7 +1538,11 @@ class ThreadActor extends Actor {
// overhead of an RDP packet for every source right now. Let the default
// timeout flush the buffered packets.
- return this.sourcesManager.iter().map(s => s.form());
+ const forms = [];
+ for (const source of this.sourcesManager.iter()) {
+ forms.push(source.form());
+ }
+ return forms;
}
/**
@@ -1809,7 +1823,7 @@ class ThreadActor extends Actor {
this.threadLifetimePool.objectActors.set(actor.obj, actor);
}
- _onWindowReady({ isTopLevel, isBFCache, window }) {
+ _onWindowReady({ isTopLevel, isBFCache }) {
// Note that this code relates to the disabling of Debugger API from will-navigate listener.
// And should only be triggered when the target actor doesn't follow WindowGlobal lifecycle.
// i.e. when the Thread Actor manages more than one top level WindowGlobal.
@@ -1817,9 +1831,6 @@ class ThreadActor extends Actor {
this.sourcesManager.reset();
this.clearDebuggees();
this.dbg.enable();
- // Update the global no matter if the debugger is on or off,
- // otherwise the global will be wrong when enabled later.
- this.global = window;
}
// Refresh the debuggee list when a new window object appears (top window or
@@ -2119,7 +2130,7 @@ class ThreadActor extends Actor {
// when debugging a tab (i.e. browser-element). As we still want to debug them
// from the browser toolbox.
if (
- this._parent.sessionContext.type == "browser-element" &&
+ this.targetActor.sessionContext.type == "browser-element" &&
source.url.endsWith("ExtensionContent.sys.mjs")
) {
return false;
@@ -2208,7 +2219,7 @@ class ThreadActor extends Actor {
// HTML files can contain any number of inline sources. We have to find
// all the inline sources and their start line without running any of the
// scripts on the page. The approach used here is approximate.
- if (!this._parent.window) {
+ if (!this.targetActor.window) {
return;
}
diff --git a/devtools/server/actors/tracer.js b/devtools/server/actors/tracer.js
index 028d084584..bf759cee5f 100644
--- a/devtools/server/actors/tracer.js
+++ b/devtools/server/actors/tracer.js
@@ -129,29 +129,40 @@ class TracerActor extends Actor {
this.tracingListener = {
onTracingFrame: this.onTracingFrame.bind(this),
+ onTracingFrameStep: this.onTracingFrameStep.bind(this),
onTracingFrameExit: this.onTracingFrameExit.bind(this),
onTracingInfiniteLoop: this.onTracingInfiniteLoop.bind(this),
onTracingToggled: this.onTracingToggled.bind(this),
onTracingPending: this.onTracingPending.bind(this),
+ onTracingDOMMutation: this.onTracingDOMMutation.bind(this),
};
addTracingListener(this.tracingListener);
this.traceValues = !!options.traceValues;
- startTracing({
- global: this.targetActor.window || this.targetActor.workerGlobal,
- prefix: options.prefix || "",
- // Enable receiving the `currentDOMEvent` being passed to `onTracingFrame`
- traceDOMEvents: true,
- // Enable tracing function arguments as well as returned values
- traceValues: !!options.traceValues,
- // Enable tracing only on next user interaction
- traceOnNextInteraction: !!options.traceOnNextInteraction,
- // Notify about frame exit / function call returning
- traceFunctionReturn: !!options.traceFunctionReturn,
- // Ignore frames beyond the given depth
- maxDepth: options.maxDepth,
- // Stop the tracing after a number of top level frames
- maxRecords: options.maxRecords,
- });
+ try {
+ startTracing({
+ global: this.targetActor.window || this.targetActor.workerGlobal,
+ prefix: options.prefix || "",
+ // Enable receiving the `currentDOMEvent` being passed to `onTracingFrame`
+ traceDOMEvents: true,
+ // Enable tracing DOM Mutations
+ traceDOMMutations: options.traceDOMMutations,
+ // Enable tracing function arguments as well as returned values
+ traceValues: !!options.traceValues,
+ // Enable tracing only on next user interaction
+ traceOnNextInteraction: !!options.traceOnNextInteraction,
+ // Notify about frame exit / function call returning
+ traceFunctionReturn: !!options.traceFunctionReturn,
+ // Ignore frames beyond the given depth
+ maxDepth: options.maxDepth,
+ // Stop the tracing after a number of top level frames
+ maxRecords: options.maxRecords,
+ });
+ } catch (e) {
+ // If startTracing throws, it probably rejected one of its options and we should
+ // unregister the tracing listener.
+ this.stopTracing();
+ throw e;
+ }
}
stopTracing() {
@@ -188,12 +199,10 @@ class TracerActor extends Actor {
*
* @param {Boolean} enabled
* True if the tracer starts tracing, false it it stops.
- * @param {String} reason
- * Optional string to justify why the tracer stopped.
* @return {Boolean}
* Return true, if the JavaScriptTracer should log a message to stdout.
*/
- onTracingToggled(enabled, reason) {
+ onTracingToggled(enabled) {
// stopTracing will clear `logMethod`, so compute this before calling it.
const shouldLogToStdout = this.logMethod == LOG_METHODS.STDOUT;
@@ -266,11 +275,111 @@ class TracerActor extends Actor {
}
/**
+ * Called by JavaScriptTracer class when a new mutation happened on any DOM Element.
+ *
+ * @param {Object} options
+ * @param {Number} options.depth
+ * Represents the depth of the frame in the call stack.
+ * @param {String} options.prefix
+ * A string to be displayed as a prefix of any logged frame.
+ * @param {nsIStackFrame} options.caller
+ * The JS Callsite which caused this mutation.
+ * @param {String} options.type
+ * Type of DOM Mutation:
+ * - "add": Node being added,
+ * - "attributes": Node whose attributes changed,
+ * - "remove": Node being removed,
+ * @param {DOMNode} options.element
+ * The DOM Node related to the current mutation.
+ */
+ onTracingDOMMutation({ depth, prefix, type, caller, element }) {
+ // Delegate to JavaScriptTracer to log to stdout
+ if (this.logMethod == LOG_METHODS.STDOUT) {
+ return true;
+ }
+
+ if (this.logMethod == LOG_METHODS.CONSOLE) {
+ const dbgObj = makeDebuggeeValue(this.targetActor, element);
+ this.throttledTraces.push({
+ resourceType: JSTRACER_TRACE,
+ prefix,
+ timeStamp: ChromeUtils.dateNow(),
+
+ filename: caller?.filename,
+ lineNumber: caller?.lineNumber,
+ columnNumber: caller?.columnNumber,
+ sourceId: caller.sourceId,
+
+ depth,
+ mutationType: type,
+ mutationElement: createValueGripForTarget(this.targetActor, dbgObj),
+ });
+ this.throttleEmitTraces();
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Called by JavaScriptTracer class on each step of a function call.
+ *
+ * @param {Object} options
+ * @param {Debugger.Frame} options.frame
+ * A descriptor object for the JavaScript frame.
+ * @param {Number} options.depth
+ * Represents the depth of the frame in the call stack.
+ * @param {String} options.prefix
+ * A string to be displayed as a prefix of any logged frame.
+ * @return {Boolean}
+ * Return true, if the JavaScriptTracer should log the step to stdout.
+ */
+ onTracingFrameStep({ frame, depth, prefix }) {
+ const { script } = frame;
+ const { lineNumber, columnNumber } = script.getOffsetMetadata(frame.offset);
+ const url = script.source.url;
+
+ // NOTE: Debugger.Script.prototype.getOffsetMetadata returns
+ // columnNumber in 1-based.
+ // Convert to 0-based, while keeping the wasm's column (1) as is.
+ // (bug 1863878)
+ const columnBase = script.format === "wasm" ? 0 : 1;
+
+ // Ignore blackboxed sources
+ if (
+ this.sourcesManager.isBlackBoxed(
+ url,
+ lineNumber,
+ columnNumber - columnBase
+ )
+ ) {
+ return false;
+ }
+
+ if (this.logMethod == LOG_METHODS.STDOUT) {
+ // By returning true, we let JavaScriptTracer class log the message to stdout.
+ return true;
+ }
+
+ if (this.logMethod == LOG_METHODS.CONSOLE) {
+ this.throttledTraces.push({
+ resourceType: JSTRACER_TRACE,
+ prefix,
+ timeStamp: ChromeUtils.dateNow(),
+
+ depth,
+ filename: url,
+ lineNumber,
+ columnNumber: columnNumber - columnBase,
+ sourceId: script.source.id,
+ });
+ this.throttleEmitTraces();
+ }
+
+ return false;
+ }
+ /**
* Called by JavaScriptTracer class when a new JavaScript frame is executed.
*
- * @param {Number} frameId
- * Unique identifier for the current frame.
- * This should match a frame notified via onTracingFrameExit.
* @param {Debugger.Frame} frame
* A descriptor object for the JavaScript frame.
* @param {Number} depth
@@ -287,7 +396,6 @@ class TracerActor extends Actor {
* Return true, if the JavaScriptTracer should log the frame to stdout.
*/
onTracingFrame({
- frameId,
frame,
depth,
formatedDisplayName,
diff --git a/devtools/server/actors/utils/custom-formatters.js b/devtools/server/actors/utils/custom-formatters.js
index e4ae20dad7..f6d8cab797 100644
--- a/devtools/server/actors/utils/custom-formatters.js
+++ b/devtools/server/actors/utils/custom-formatters.js
@@ -71,7 +71,7 @@ function customFormatterHeader(objectActor) {
return null;
}
- const targetActor = objectActor.thread._parent;
+ const { targetActor } = objectActor.thread;
const {
customFormatterConfigDbgObj: configDbgObj,
@@ -253,7 +253,7 @@ async function customFormatterBody(objectActor, formatter) {
const customFormatterIndex = global.devtoolsFormatters.indexOf(formatter);
- const targetActor = objectActor.thread._parent;
+ const { targetActor } = objectActor.thread;
try {
const { customFormatterConfigDbgObj, customFormatterObjectTagDepth } =
objectActor.hooks;
diff --git a/devtools/server/actors/utils/inactive-property-helper.js b/devtools/server/actors/utils/inactive-property-helper.js
index 759c2e6215..3f6e748167 100644
--- a/devtools/server/actors/utils/inactive-property-helper.js
+++ b/devtools/server/actors/utils/inactive-property-helper.js
@@ -21,6 +21,11 @@ const TEXT_WRAP_BALANCE_LIMIT = Services.prefs.getIntPref(
10
);
+const ALIGN_CONTENT_BLOCKS = Services.prefs.getBoolPref(
+ "layout.css.align-content.blocks.enabled",
+ false
+);
+
const VISITED_MDN_LINK = "https://developer.mozilla.org/docs/Web/CSS/:visited";
const VISITED_INVALID_PROPERTIES = allCssPropertiesExcept([
"all",
@@ -227,12 +232,29 @@ class InactivePropertyHelper {
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1598730
{
invalidProperties: ["align-content"],
- when: () =>
- !this.style["align-content"].includes("baseline") &&
- !this.gridContainer &&
- !this.flexContainer,
- fixId: "inactive-css-not-grid-or-flex-container-fix",
- msgId: "inactive-css-not-grid-or-flex-container",
+ when: () => {
+ if (this.style["align-content"].includes("baseline")) {
+ return false;
+ }
+ const supportedDisplay = [
+ "flex",
+ "inline-flex",
+ "grid",
+ "inline-grid",
+ // Uncomment table-cell when Bug 1883357 is fixed.
+ // "table-cell"
+ ];
+ if (ALIGN_CONTENT_BLOCKS) {
+ supportedDisplay.push("block", "inline-block");
+ }
+ return !this.checkComputedStyle("display", supportedDisplay);
+ },
+ fixId: ALIGN_CONTENT_BLOCKS
+ ? "inactive-css-not-grid-or-flex-or-block-container-fix"
+ : "inactive-css-not-grid-or-flex-container-fix",
+ msgId: ALIGN_CONTENT_BLOCKS
+ ? "inactive-css-property-because-of-display"
+ : "inactive-css-not-grid-or-flex-container",
},
// column-gap and shorthands used on non-grid or non-flex or non-multi-col container.
{
@@ -1223,11 +1245,8 @@ class InactivePropertyHelper {
/**
* Check if a node is a grid item.
- *
- * @param {DOMNode} node
- * The node to check.
*/
- isGridItem(node) {
+ isGridItem() {
return !!this.getParentGridElement(this.node);
}
diff --git a/devtools/server/actors/utils/logEvent.js b/devtools/server/actors/utils/logEvent.js
index 88b166619e..5f40085fde 100644
--- a/devtools/server/actors/utils/logEvent.js
+++ b/devtools/server/actors/utils/logEvent.js
@@ -34,7 +34,7 @@ function logEvent({ threadActor, frame, level, expression, bindings }) {
// TODO remove this branch when (#1592584) lands (#1609540)
if (isWorker) {
- threadActor._parent._consoleActor.evaluateJS({
+ threadActor.targetActor._consoleActor.evaluateJS({
text: `console.log(...${expression})`,
bindings: { displayName, ...bindings },
url: sourceActor.url,
@@ -76,7 +76,7 @@ function logEvent({ threadActor, frame, level, expression, bindings }) {
value = value.unsafeDereference();
}
- const targetActor = threadActor._parent;
+ const targetActor = threadActor.targetActor;
const message = {
filename: sourceActor.url,
lineNumber: line,
diff --git a/devtools/server/actors/utils/sources-manager.js b/devtools/server/actors/utils/sources-manager.js
index b80da69bfa..fda37a3184 100644
--- a/devtools/server/actors/utils/sources-manager.js
+++ b/devtools/server/actors/utils/sources-manager.js
@@ -341,8 +341,13 @@ class SourcesManager extends EventEmitter {
return this.blackBoxedSources.set(url, ranges);
}
+ /**
+ * List all currently registered source actors.
+ *
+ * @return Iterator<SourceActor>
+ */
iter() {
- return [...this._sourceActors.values()];
+ return this._sourceActors.values();
}
/**
@@ -429,15 +434,15 @@ class SourcesManager extends EventEmitter {
// Without this check, the cache may return stale data that doesn't match
// the document shown in the browser.
let loadFromCache = canUseCache;
- if (canUseCache && this._thread._parent.browsingContext) {
+ if (canUseCache && this._thread.targetActor.browsingContext) {
loadFromCache = !(
- this._thread._parent.browsingContext.defaultLoadFlags ===
+ this._thread.targetActor.browsingContext.defaultLoadFlags ===
Ci.nsIRequest.LOAD_BYPASS_CACHE
);
}
// Fetch the sources with the same principal as the original document
- const win = this._thread._parent.window;
+ const win = this._thread.targetActor.window;
let principal, cacheKey;
// On xpcshell, we don't have a window but a Sandbox
if (!isWorker && win instanceof Ci.nsIDOMWindow) {
diff --git a/devtools/server/actors/utils/stylesheets-manager.js b/devtools/server/actors/utils/stylesheets-manager.js
index 838e5be602..a9c0705e8d 100644
--- a/devtools/server/actors/utils/stylesheets-manager.js
+++ b/devtools/server/actors/utils/stylesheets-manager.js
@@ -640,10 +640,14 @@ class StyleSheetsManager extends EventEmitter {
return win;
};
- const styleSheetRules =
- InspectorUtils.getAllStyleSheetCSSStyleRules(styleSheet);
- const ruleCount = styleSheetRules.length;
- // We need to go through nested rules to extract all the rules we're interested in
+ // This returns the following type of at-rules:
+ // - CSSMediaRule
+ // - CSSContainerRule
+ // - CSSSupportsRule
+ // - CSSLayerBlockRule
+ // New types can be added from InpsectorUtils.cpp `CollectAtRules`
+ const { atRules: styleSheetRules, ruleCount } =
+ InspectorUtils.getStyleSheetRuleCountAndAtRules(styleSheet);
const atRules = [];
for (const rule of styleSheetRules) {
const className = ChromeUtils.getClassName(rule);
@@ -703,7 +707,10 @@ class StyleSheetsManager extends EventEmitter {
});
}
}
- return { ruleCount, atRules };
+ return {
+ ruleCount,
+ atRules,
+ };
}
/**
diff --git a/devtools/server/actors/watcher.js b/devtools/server/actors/watcher.js
index 97d2be01e4..935d33faa8 100644
--- a/devtools/server/actors/watcher.js
+++ b/devtools/server/actors/watcher.js
@@ -9,21 +9,18 @@ const { watcherSpec } = require("resource://devtools/shared/specs/watcher.js");
const Resources = require("resource://devtools/server/actors/resources/index.js");
const { TargetActorRegistry } = ChromeUtils.importESModule(
"resource://devtools/server/actors/targets/target-actor-registry.sys.mjs",
- {
- loadInDevToolsLoader: false,
- }
+ { global: "shared" }
);
const { WatcherRegistry } = ChromeUtils.importESModule(
"resource://devtools/server/actors/watcher/WatcherRegistry.sys.mjs",
- {
- // WatcherRegistry needs to be a true singleton and loads ActorManagerParent
- // which also has to be a true singleton.
- loadInDevToolsLoader: false,
- }
+ // WatcherRegistry needs to be a true singleton and loads ActorManagerParent
+ // which also has to be a true singleton.
+ { global: "shared" }
);
const Targets = require("resource://devtools/server/actors/targets/index.js");
const { getAllBrowsingContextsForContext } = ChromeUtils.importESModule(
- "resource://devtools/server/actors/watcher/browsing-context-helpers.sys.mjs"
+ "resource://devtools/server/actors/watcher/browsing-context-helpers.sys.mjs",
+ { global: "contextual" }
);
const {
SESSION_TYPES,
@@ -257,11 +254,11 @@ exports.WatcherActor = class WatcherActor extends Actor {
const targetHelperModule = TARGET_HELPERS[targetType];
targetHelperModule.destroyTargets(this, options);
- // Unregister the JS Window Actor if there is no more DevTools code observing any target/resource,
+ // Unregister the JS Actors if there is no more DevTools code observing any target/resource,
// unless we're switching mode (having both condition at the same time should only
// happen in tests).
if (!options.isModeSwitching) {
- WatcherRegistry.maybeUnregisteringJSWindowActor();
+ WatcherRegistry.maybeUnregisterJSActors();
}
}
@@ -637,7 +634,7 @@ exports.WatcherActor = class WatcherActor extends Actor {
}
// Unregister the JS Window Actor if there is no more DevTools code observing any target/resource
- WatcherRegistry.maybeUnregisteringJSWindowActor();
+ WatcherRegistry.maybeUnregisterJSActors();
}
clearResources(resourceTypes) {
diff --git a/devtools/server/actors/watcher/WatcherRegistry.sys.mjs b/devtools/server/actors/watcher/WatcherRegistry.sys.mjs
index 1068a253c9..ac8bc7f0c8 100644
--- a/devtools/server/actors/watcher/WatcherRegistry.sys.mjs
+++ b/devtools/server/actors/watcher/WatcherRegistry.sys.mjs
@@ -180,6 +180,9 @@ export const WatcherRegistry = {
// Register the JS Window Actor the first time we start watching for something (e.g. resource, target, …).
registerJSWindowActor();
+ if (sessionData?.targets?.includes("process")) {
+ registerJSProcessActor();
+ }
persistMapToSharedData();
},
@@ -245,7 +248,17 @@ export const WatcherRegistry = {
unregisterWatcher(watcher) {
sessionDataByWatcherActor.delete(watcher.actorID);
watcherActors.delete(watcher.actorID);
- this.maybeUnregisteringJSWindowActor();
+ this.maybeUnregisterJSActors();
+ },
+
+ /**
+ * Unregister the JS Actors if there is no more DevTools code observing any target/resource.
+ */
+ maybeUnregisterJSActors() {
+ if (sessionDataByWatcherActor.size == 0) {
+ unregisterJSWindowActor();
+ unregisterJSProcessActor();
+ }
},
/**
@@ -319,15 +332,6 @@ export const WatcherRegistry = {
resourceTypes
);
},
-
- /**
- * Unregister the JS Window Actor if there is no more DevTools code observing any target/resource.
- */
- maybeUnregisteringJSWindowActor() {
- if (sessionDataByWatcherActor.size == 0) {
- unregisterJSWindowActor();
- }
- },
};
// Boolean flag to know if the DevToolsFrame JS Window Actor is currently registered
@@ -395,3 +399,63 @@ function unregisterJSWindowActor() {
ChromeUtils.unregisterWindowActor(JSWindowActorName);
}
}
+
+// Boolean flag to know if the DevToolsProcess JS Process Actor is currently registered
+let isJSProcessActorRegistered = false;
+
+const JSProcessActorConfig = {
+ parent: {
+ esModuleURI:
+ "resource://devtools/server/connectors/js-process-actor/DevToolsProcessParent.sys.mjs",
+ },
+ child: {
+ esModuleURI:
+ "resource://devtools/server/connectors/js-process-actor/DevToolsProcessChild.sys.mjs",
+ // There is no good observer service notification we can listen to to instantiate the JSProcess Actor
+ // reliably as soon as the process start.
+ // So manually spawn our JSProcessActor from a process script emitting a custom observer service notification...
+ observers: ["init-devtools-content-process-actor"],
+ },
+ // The parent process is handled very differently from content processes
+ // This uses the ParentProcessTarget which inherits from BrowsingContextTarget
+ // and is, for now, manually created by the descriptor as the top level target.
+ includeParent: false,
+
+ // This JS Process Actor is used to bootstrap DevTools code debugging the privileged code
+ // in content processes. The privileged code runs in the "shared JSM global" (See mozJSModuleLoader).
+ // DevTools modules should be loaded in a distinct global in order to be able to debug this privileged code.
+ // There is a strong requirement in spidermonkey for the debuggee and debugger to be using distinct compartments.
+ // This flag will force both parent and child modules to be loaded via a dedicated loader (See mozJSModuleLoader::GetOrCreateDevToolsLoader)
+ //
+ // Note that as a side effect, it makes these modules and all their dependencies to be invisible to the debugger.
+ loadInDevToolsLoader: true,
+};
+
+const PROCESS_SCRIPT_URL =
+ "resource://devtools/server/actors/watcher/target-helpers/content-process-jsprocessactor-startup.js";
+
+function registerJSProcessActor() {
+ if (isJSProcessActorRegistered) {
+ return;
+ }
+ isJSProcessActorRegistered = true;
+ ChromeUtils.registerProcessActor("DevToolsProcess", JSProcessActorConfig);
+
+ // There is no good observer service notification we can listen to to instantiate the JSProcess Actor
+ // as soon as the process start.
+ // So manually spawn our JSProcessActor from a process script emitting a custom observer service notification...
+ Services.ppmm.loadProcessScript(PROCESS_SCRIPT_URL, true);
+}
+
+function unregisterJSProcessActor() {
+ if (!isJSProcessActorRegistered) {
+ return;
+ }
+ isJSProcessActorRegistered = false;
+ try {
+ ChromeUtils.unregisterProcessActor("DevToolsProcess");
+ } catch (e) {
+ // If any pending query was still ongoing, this would throw
+ }
+ Services.ppmm.removeDelayedProcessScript(PROCESS_SCRIPT_URL);
+}
diff --git a/devtools/server/actors/watcher/target-helpers/content-process-jsprocessactor-startup.js b/devtools/server/actors/watcher/target-helpers/content-process-jsprocessactor-startup.js
new file mode 100644
index 0000000000..1765bcc66c
--- /dev/null
+++ b/devtools/server/actors/watcher/target-helpers/content-process-jsprocessactor-startup.js
@@ -0,0 +1,26 @@
+/* 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/. */
+
+"use strict";
+
+const { setTimeout } = ChromeUtils.importESModule(
+ "resource://gre/modules/Timer.sys.mjs"
+);
+
+/*
+ We can't spawn the JSProcessActor right away and have to spin the event loop.
+ Otherwise it isn't registered yet and isn't listening to observer service.
+ Could it be the reason why JSProcessActor aren't spawn via process actor option's child.observers notifications ??
+*/
+setTimeout(function () {
+ /*
+ This notification is registered in DevToolsServiceWorker JS process actor's options's `observers` attribute
+ and will force the JS Process actor to be instantiated in all processes.
+ */
+ Services.obs.notifyObservers(null, "init-devtools-content-process-actor");
+ /*
+ Instead of using observer service, we could also manually call some method of the actor:
+ ChromeUtils.domProcessChild.getActor("DevToolsProcess").observe(null, "foo");
+ */
+}, 0);
diff --git a/devtools/server/actors/watcher/target-helpers/frame-helper.js b/devtools/server/actors/watcher/target-helpers/frame-helper.js
index 0e6f4f80d3..18d4d8f92e 100644
--- a/devtools/server/actors/watcher/target-helpers/frame-helper.js
+++ b/devtools/server/actors/watcher/target-helpers/frame-helper.js
@@ -6,14 +6,13 @@
const { WatcherRegistry } = ChromeUtils.importESModule(
"resource://devtools/server/actors/watcher/WatcherRegistry.sys.mjs",
- {
- // WatcherRegistry needs to be a true singleton and loads ActorManagerParent
- // which also has to be a true singleton.
- loadInDevToolsLoader: false,
- }
+ // WatcherRegistry needs to be a true singleton and loads ActorManagerParent
+ // which also has to be a true singleton.
+ { global: "shared" }
);
const { WindowGlobalLogger } = ChromeUtils.importESModule(
- "resource://devtools/server/connectors/js-window-actor/WindowGlobalLogger.sys.mjs"
+ "resource://devtools/server/connectors/js-window-actor/WindowGlobalLogger.sys.mjs",
+ { global: "contextual" }
);
const Targets = require("resource://devtools/server/actors/targets/index.js");
diff --git a/devtools/server/actors/watcher/target-helpers/moz.build b/devtools/server/actors/watcher/target-helpers/moz.build
index b7c8983590..3b00f0ef47 100644
--- a/devtools/server/actors/watcher/target-helpers/moz.build
+++ b/devtools/server/actors/watcher/target-helpers/moz.build
@@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
+ "content-process-jsprocessactor-startup.js",
"frame-helper.js",
"process-helper.js",
"service-worker-helper.js",
diff --git a/devtools/server/actors/watcher/target-helpers/process-helper.js b/devtools/server/actors/watcher/target-helpers/process-helper.js
index 8895d7ed66..e36f0a204c 100644
--- a/devtools/server/actors/watcher/target-helpers/process-helper.js
+++ b/devtools/server/actors/watcher/target-helpers/process-helper.js
@@ -4,205 +4,36 @@
"use strict";
-const { WatcherRegistry } = ChromeUtils.importESModule(
- "resource://devtools/server/actors/watcher/WatcherRegistry.sys.mjs",
- {
- // WatcherRegistry needs to be a true singleton and loads ActorManagerParent
- // which also has to be a true singleton.
- loadInDevToolsLoader: false,
- }
-);
-
-loader.lazyRequireGetter(
- this,
- "ChildDebuggerTransport",
- "resource://devtools/shared/transport/child-transport.js",
- true
-);
-
-const CONTENT_PROCESS_SCRIPT =
- "resource://devtools/server/startup/content-process-script.js";
-
/**
- * Map a MessageManager key to an Array of ContentProcessTargetActor "description" objects.
- * A single MessageManager might be linked to several ContentProcessTargetActors if there are several
- * Watcher actors instantiated on the DevToolsServer, via a single connection (in theory), but rather
- * via distinct connections (ex: a content toolbox and the browser toolbox).
- * Note that if we spawn two DevToolsServer, this module will be instantiated twice.
+ * Return the list of all DOM Processes except the one for the parent process
*
- * Each ContentProcessTargetActor "description" object is structured as follows
- * - {Object} actor: form of the content process target actor
- * - {String} prefix: forwarding prefix used to redirect all packet to the right content process's transport
- * - {ChildDebuggerTransport} childTransport: Transport forwarding all packets to the target's content process
- * - {WatcherActor} watcher: The Watcher actor for which we instantiated this content process target actor
+ * @return Array<nsIDOMProcessParent>
*/
-const actors = new WeakMap();
-
-// Save the list of all watcher actors that are watching for processes
-const watchers = new Set();
-
-function onContentProcessActorCreated(msg) {
- const { watcherActorID, prefix, actor } = msg.data;
- const watcher = WatcherRegistry.getWatcher(watcherActorID);
- if (!watcher) {
- throw new Error(
- `Receiving a content process actor without a watcher actor ${watcherActorID}`
- );
- }
- // Ignore watchers of other connections.
- // We may have two browser toolbox connected to the same process.
- // This will spawn two distinct Watcher actor and two distinct process target helper module.
- // Avoid processing the event many times, otherwise we will notify about the same target
- // multiple times.
- if (!watchers.has(watcher)) {
- return;
- }
- const messageManager = msg.target;
- const connection = watcher.conn;
-
- // Pipe Debugger message from/to parent/child via the message manager
- const childTransport = new ChildDebuggerTransport(messageManager, prefix);
- childTransport.hooks = {
- onPacket: connection.send.bind(connection),
- };
- childTransport.ready();
-
- connection.setForwarding(prefix, childTransport);
-
- const list = actors.get(messageManager) || [];
- list.push({
- prefix,
- childTransport,
- actor,
- watcher,
- });
- actors.set(messageManager, list);
-
- watcher.notifyTargetAvailable(actor);
-}
-
-function onContentProcessActorDestroyed(msg) {
- const { watcherActorID } = msg.data;
- const watcher = WatcherRegistry.getWatcher(watcherActorID);
- if (!watcher) {
- throw new Error(
- `Receiving a content process actor destruction without a watcher actor ${watcherActorID}`
- );
- }
- // Ignore watchers of other connections.
- // We may have two browser toolbox connected to the same process.
- // This will spawn two distinct Watcher actor and two distinct process target helper module.
- // Avoid processing the event many times, otherwise we will notify about the same target
- // multiple times.
- if (!watchers.has(watcher)) {
- return;
- }
- const messageManager = msg.target;
- unregisterWatcherForMessageManager(watcher, messageManager);
-}
-
-function onMessageManagerClose(messageManager, topic, data) {
- const list = actors.get(messageManager);
- if (!list || !list.length) {
- return;
- }
- for (const { prefix, childTransport, actor, watcher } of list) {
- watcher.notifyTargetDestroyed(actor);
-
- // If we have a child transport, the actor has already
- // been created. We need to stop using this message manager.
- childTransport.close();
- watcher.conn.cancelForwarding(prefix);
- }
- actors.delete(messageManager);
-}
-
-/**
- * Unregister everything created for a given watcher against a precise message manager:
- * - clear up things from `actors` WeakMap,
- * - notify all related target actors as being destroyed,
- * - close all DevTools Transports being created for each Message Manager.
- *
- * @param {WatcherActor} watcher
- * @param {MessageManager}
- * @param {object} options
- * @param {boolean} options.isModeSwitching
- * true when this is called as the result of a change to the devtools.browsertoolbox.scope pref
- */
-function unregisterWatcherForMessageManager(watcher, messageManager, options) {
- const targetActorDescriptions = actors.get(messageManager);
- if (!targetActorDescriptions || !targetActorDescriptions.length) {
- return;
- }
-
- // Destroy all transports related to this watcher and tells the client to purge all related actors
- const matchingTargetActorDescriptions = targetActorDescriptions.filter(
- item => item.watcher === watcher
+function getAllContentProcesses() {
+ return ChromeUtils.getAllDOMProcesses().filter(
+ process => process.childID !== 0
);
- for (const {
- prefix,
- childTransport,
- actor,
- } of matchingTargetActorDescriptions) {
- watcher.notifyTargetDestroyed(actor, options);
-
- childTransport.close();
- watcher.conn.cancelForwarding(prefix);
- }
-
- // Then update global `actors` WeakMap by stripping all data about this watcher
- const remainingTargetActorDescriptions = targetActorDescriptions.filter(
- item => item.watcher !== watcher
- );
- if (!remainingTargetActorDescriptions.length) {
- actors.delete(messageManager);
- } else {
- actors.set(messageManager, remainingTargetActorDescriptions);
- }
}
/**
- * Destroy everything related to a given watcher that has been created in this module:
- * (See unregisterWatcherForMessageManager)
+ * Instantiate all Content Process targets in all the DOM Processes.
*
* @param {WatcherActor} watcher
- * @param {object} options
- * @param {boolean} options.isModeSwitching
- * true when this is called as the result of a change to the devtools.browsertoolbox.scope pref
*/
-function closeWatcherTransports(watcher, options) {
- for (let i = 0; i < Services.ppmm.childCount; i++) {
- const messageManager = Services.ppmm.getChildAt(i);
- unregisterWatcherForMessageManager(watcher, messageManager, options);
- }
-}
-
-function maybeRegisterMessageListeners(watcher) {
- const sizeBefore = watchers.size;
- watchers.add(watcher);
- if (sizeBefore == 0 && watchers.size == 1) {
- Services.ppmm.addMessageListener(
- "debug:content-process-actor",
- onContentProcessActorCreated
- );
- Services.ppmm.addMessageListener(
- "debug:content-process-actor-destroyed",
- onContentProcessActorDestroyed
+async function createTargets(watcher) {
+ const promises = [];
+ for (const domProcess of getAllContentProcesses()) {
+ const processActor = domProcess.getActor("DevToolsProcess");
+ promises.push(
+ processActor.instantiateTarget({
+ watcherActorID: watcher.actorID,
+ connectionPrefix: watcher.conn.prefix,
+ sessionContext: watcher.sessionContext,
+ sessionData: watcher.sessionData,
+ })
);
- Services.obs.addObserver(onMessageManagerClose, "message-manager-close");
-
- // Load the content process server startup script only once,
- // otherwise it will be evaluated twice, listen to events twice and create
- // target actors twice.
- // We may try to load it twice when opening one Browser Toolbox via about:debugging
- // and another regular Browser Toolbox. Both will spawn a WatcherActor and watch for processes.
- const isContentProcessScripLoaded = Services.ppmm
- .getDelayedProcessScripts()
- .some(([uri]) => uri === CONTENT_PROCESS_SCRIPT);
- if (!isContentProcessScripLoaded) {
- Services.ppmm.loadProcessScript(CONTENT_PROCESS_SCRIPT, true);
- }
}
+ await Promise.all(promises);
}
/**
@@ -211,96 +42,16 @@ function maybeRegisterMessageListeners(watcher) {
* @param {boolean} options.isModeSwitching
* true when this is called as the result of a change to the devtools.browsertoolbox.scope pref
*/
-function maybeUnregisterMessageListeners(watcher, options = {}) {
- const sizeBefore = watchers.size;
- watchers.delete(watcher);
- closeWatcherTransports(watcher, options);
-
- if (sizeBefore == 1 && watchers.size == 0) {
- Services.ppmm.removeMessageListener(
- "debug:content-process-actor",
- onContentProcessActorCreated
- );
- Services.ppmm.removeMessageListener(
- "debug:content-process-actor-destroyed",
- onContentProcessActorDestroyed
- );
- Services.obs.removeObserver(onMessageManagerClose, "message-manager-close");
-
- // We inconditionally remove the process script, while we should only remove it
- // once the last DevToolsServer stop watching for processes.
- // We might have many server, using distinct loaders, so that this module
- // will be spawn many times and we should remove the script only once the last
- // module unregister the last watcher of all.
- Services.ppmm.removeDelayedProcessScript(CONTENT_PROCESS_SCRIPT);
-
- Services.ppmm.broadcastAsyncMessage("debug:destroy-process-script", {
- options,
+function destroyTargets(watcher, options) {
+ for (const domProcess of getAllContentProcesses()) {
+ const processActor = domProcess.getActor("DevToolsProcess");
+ processActor.destroyTarget({
+ watcherActorID: watcher.actorID,
+ isModeSwitching: options.isModeSwitching,
});
}
}
-async function createTargets(watcher) {
- // XXX: Should this move to WatcherRegistry??
- maybeRegisterMessageListeners(watcher);
-
- // Bug 1648499: This could be simplified when migrating to JSProcessActor by using sendQuery.
- // For now, hack into WatcherActor in order to know when we created one target
- // actor for each existing content process.
- // Also, we substract one as the parent process has a message manager and is counted
- // in `childCount`, but we ignore it from the process script and it won't reply.
- let contentProcessCount = Services.ppmm.childCount - 1;
- if (contentProcessCount == 0) {
- return;
- }
- const onTargetsCreated = new Promise(resolve => {
- let receivedTargetCount = 0;
- const listener = () => {
- receivedTargetCount++;
- mayBeResolve();
- };
- watcher.on("target-available-form", listener);
- const onContentProcessClosed = () => {
- // Update the content process count as one has been just destroyed
- contentProcessCount--;
- mayBeResolve();
- };
- Services.obs.addObserver(onContentProcessClosed, "message-manager-close");
- function mayBeResolve() {
- if (receivedTargetCount >= contentProcessCount) {
- watcher.off("target-available-form", listener);
- Services.obs.removeObserver(
- onContentProcessClosed,
- "message-manager-close"
- );
- resolve();
- }
- }
- });
-
- Services.ppmm.broadcastAsyncMessage("debug:instantiate-already-available", {
- watcherActorID: watcher.actorID,
- connectionPrefix: watcher.conn.prefix,
- sessionData: watcher.sessionData,
- });
-
- await onTargetsCreated;
-}
-
-/**
- * @param {WatcherActor} watcher
- * @param {object} options
- * @param {boolean} options.isModeSwitching
- * true when this is called as the result of a change to the devtools.browsertoolbox.scope pref
- */
-function destroyTargets(watcher, options) {
- maybeUnregisterMessageListeners(watcher, options);
-
- Services.ppmm.broadcastAsyncMessage("debug:destroy-target", {
- watcherActorID: watcher.actorID,
- });
-}
-
/**
* Go over all existing content processes in order to communicate about new data entries
*
@@ -321,51 +72,19 @@ async function addOrSetSessionDataEntry({
entries,
updateType,
}) {
- let expectedCount = Services.ppmm.childCount - 1;
- if (expectedCount == 0) {
- return;
- }
- const onAllReplied = new Promise(resolve => {
- let count = 0;
- const listener = msg => {
- if (msg.data.watcherActorID != watcher.actorID) {
- return;
- }
- count++;
- maybeResolve();
- };
- Services.ppmm.addMessageListener(
- "debug:add-or-set-session-data-entry-done",
- listener
+ const promises = [];
+ for (const domProcess of getAllContentProcesses()) {
+ const processActor = domProcess.getActor("DevToolsProcess");
+ promises.push(
+ processActor.addOrSetSessionDataEntry({
+ watcherActorID: watcher.actorID,
+ type,
+ entries,
+ updateType,
+ })
);
- const onContentProcessClosed = (messageManager, topic, data) => {
- expectedCount--;
- maybeResolve();
- };
- const maybeResolve = () => {
- if (count == expectedCount) {
- Services.ppmm.removeMessageListener(
- "debug:add-or-set-session-data-entry-done",
- listener
- );
- Services.obs.removeObserver(
- onContentProcessClosed,
- "message-manager-close"
- );
- resolve();
- }
- };
- Services.obs.addObserver(onContentProcessClosed, "message-manager-close");
- });
-
- Services.ppmm.broadcastAsyncMessage("debug:add-or-set-session-data-entry", {
- watcherActorID: watcher.actorID,
- type,
- entries,
- updateType,
- });
-
- await onAllReplied;
+ }
+ await Promise.all(promises);
}
/**
@@ -373,12 +92,19 @@ async function addOrSetSessionDataEntry({
*
* See addOrSetSessionDataEntry for argument documentation.
*/
-function removeSessionDataEntry({ watcher, type, entries }) {
- Services.ppmm.broadcastAsyncMessage("debug:remove-session-data-entry", {
- watcherActorID: watcher.actorID,
- type,
- entries,
- });
+async function removeSessionDataEntry({ watcher, type, entries }) {
+ const promises = [];
+ for (const domProcess of getAllContentProcesses()) {
+ const processActor = domProcess.getActor("DevToolsProcess");
+ promises.push(
+ processActor.removeSessionDataEntry({
+ watcherActorID: watcher.actorID,
+ type,
+ entries,
+ })
+ );
+ }
+ await Promise.all(promises);
}
module.exports = {
diff --git a/devtools/server/actors/webbrowser.js b/devtools/server/actors/webbrowser.js
index c05a863839..89db57a642 100644
--- a/devtools/server/actors/webbrowser.js
+++ b/devtools/server/actors/webbrowser.js
@@ -52,7 +52,7 @@ const lazy = {};
loader.lazyGetter(lazy, "AddonManager", () => {
return ChromeUtils.importESModule(
"resource://gre/modules/AddonManager.sys.mjs",
- { loadInDevToolsLoader: false }
+ { global: "shared" }
).AddonManager;
});
@@ -710,35 +710,35 @@ Object.defineProperty(BrowserAddonList.prototype, "onListChanged", {
/**
* AddonManager listener must implement onDisabled.
*/
-BrowserAddonList.prototype.onDisabled = function (addon) {
+BrowserAddonList.prototype.onDisabled = function () {
this._onAddonManagerUpdated();
};
/**
* AddonManager listener must implement onEnabled.
*/
-BrowserAddonList.prototype.onEnabled = function (addon) {
+BrowserAddonList.prototype.onEnabled = function () {
this._onAddonManagerUpdated();
};
/**
* AddonManager listener must implement onInstalled.
*/
-BrowserAddonList.prototype.onInstalled = function (addon) {
+BrowserAddonList.prototype.onInstalled = function () {
this._onAddonManagerUpdated();
};
/**
* AddonManager listener must implement onOperationCancelled.
*/
-BrowserAddonList.prototype.onOperationCancelled = function (addon) {
+BrowserAddonList.prototype.onOperationCancelled = function () {
this._onAddonManagerUpdated();
};
/**
* AddonManager listener must implement onUninstalling.
*/
-BrowserAddonList.prototype.onUninstalling = function (addon) {
+BrowserAddonList.prototype.onUninstalling = function () {
this._onAddonManagerUpdated();
};
@@ -750,7 +750,7 @@ BrowserAddonList.prototype.onUninstalled = function (addon) {
this._onAddonManagerUpdated();
};
-BrowserAddonList.prototype._onAddonManagerUpdated = function (addon) {
+BrowserAddonList.prototype._onAddonManagerUpdated = function () {
this._notifyListChanged();
this._adjustListener();
};
diff --git a/devtools/server/actors/webconsole.js b/devtools/server/actors/webconsole.js
index 14401b3fbe..3de636be96 100644
--- a/devtools/server/actors/webconsole.js
+++ b/devtools/server/actors/webconsole.js
@@ -1704,7 +1704,7 @@ class WebConsoleActor extends Actor {
* The "will-navigate" progress listener. This is used to clear the current
* eval scope.
*/
- _onWillNavigate({ window, isTopLevel }) {
+ _onWillNavigate({ isTopLevel }) {
if (isTopLevel) {
this._evalGlobal = null;
EventEmitter.off(this.parentActor, "will-navigate", this._onWillNavigate);
diff --git a/devtools/server/actors/webconsole/commands/experimental-commands.ftl b/devtools/server/actors/webconsole/commands/experimental-commands.ftl
index b11c29006b..66cb9d151e 100644
--- a/devtools/server/actors/webconsole/commands/experimental-commands.ftl
+++ b/devtools/server/actors/webconsole/commands/experimental-commands.ftl
@@ -9,13 +9,29 @@
webconsole-commands-usage-trace3 =
:trace
- Toggles the JavaScript tracer
+ Toggles the JavaScript tracer.
+
+ The tracer will display all functions being called by your page.
It supports the following arguments:
- --logMethod to be set to ‘console’ for logging to the web console (the default), or ‘stdout’ for logging to the standard output,
+ --logMethod to be set to ‘console’ for logging to the web console (the default), or ‘stdout’ for logging to the standard output.
+
+ --return Optional flag to be passed to also log when functions return.
+
--values Optional flag to be passed to log function call arguments as well as returned values (when returned frames are enabled).
+
--on-next-interaction Optional flag, when set, the tracer will only start on next mousedown or keydown event.
+
+ --dom-mutations Optional flag, when set, the tracer will log all DOM Mutations.
+ When passing a value, you can restrict to a particular mutation type via a coma-separated list:
+ - ‘add’ will only track DOM Node being added,
+ - ‘attributes’ will only track DOM Node whose attributes changed,
+ - ‘remove’ will only track DOM Node being removed.
+
--max-depth Optional flag, will restrict logging trace to a given depth passed as argument.
+
--max-records Optional flag, will automatically stop the tracer after having logged the passed amount of top level frames.
- --prefix Optional string which will be logged in front of all the trace logs,
+
+ --prefix Optional string which will be logged in front of all the trace logs.
+
--help or --usage to show this message.
diff --git a/devtools/server/actors/webconsole/commands/manager.js b/devtools/server/actors/webconsole/commands/manager.js
index 538ee7eac1..025e197e3b 100644
--- a/devtools/server/actors/webconsole/commands/manager.js
+++ b/devtools/server/actors/webconsole/commands/manager.js
@@ -11,6 +11,13 @@ loader.lazyRequireGetter(
true
);
+loader.lazyRequireGetter(
+ this,
+ ["DOM_MUTATIONS"],
+ "resource://devtools/server/tracer/tracer.jsm",
+ true
+);
+
loader.lazyGetter(this, "l10n", () => {
return new Localization(
[
@@ -88,7 +95,7 @@ const WebConsoleCommandsManager = {
* }
* });
*/
- register({ name, isSideEffectFree, command, validArguments, usage }) {
+ register({ name, isSideEffectFree, command, validArguments }) {
if (
typeof command != "function" &&
!(typeof command == "object" && typeof command.get == "function")
@@ -684,7 +691,7 @@ WebConsoleCommandsManager.register({
WebConsoleCommandsManager.register({
name: "help",
isSideEffectFree: false,
- command(owner, args) {
+ command(owner) {
owner.helperResult = { type: "help" };
},
});
@@ -873,13 +880,35 @@ WebConsoleCommandsManager.register({
const tracerActor =
owner.consoleActor.parentActor.getTargetScopedActor("tracer");
const logMethod = args.logMethod || "console";
+ let traceDOMMutations = null;
+ if ("dom-mutations" in args) {
+ // When no value is passed, track all types of mutations
+ if (args["dom-mutations"] === true) {
+ traceDOMMutations = ["add", "attributes", "remove"];
+ } else if (typeof args["dom-mutations"] == "string") {
+ // Otherwise consider the value as coma seperated list and remove any white space.
+ traceDOMMutations = args["dom-mutations"].split(",").map(e => e.trim());
+ const acceptedValues = Object.values(DOM_MUTATIONS);
+ if (!traceDOMMutations.every(e => acceptedValues.includes(e))) {
+ throw new Error(
+ `:trace --dom-mutations only accept a list of strings whose values can be: ${acceptedValues}`
+ );
+ }
+ } else {
+ throw new Error(
+ ":trace --dom-mutations accept only no arguments, or a list mutation type strings (add,attributes,remove)"
+ );
+ }
+ }
// Note that toggleTracing does some sanity checks and will throw meaningful error
// when the arguments are wrong.
const enabled = tracerActor.toggleTracing({
logMethod,
prefix: args.prefix || null,
+ traceFunctionReturn: !!args.returns,
traceValues: !!args.values,
traceOnNextInteraction: args["on-next-interaction"] || null,
+ traceDOMMutations,
maxDepth: args["max-depth"] || null,
maxRecords: args["max-records"] || null,
});
@@ -895,7 +924,9 @@ WebConsoleCommandsManager.register({
"max-depth",
"max-records",
"on-next-interaction",
+ "dom-mutations",
"prefix",
+ "returns",
"values",
],
});
diff --git a/devtools/server/actors/webconsole/eager-ecma-allowlist.js b/devtools/server/actors/webconsole/eager-ecma-allowlist.js
index defe98ad8b..041a4c4194 100644
--- a/devtools/server/actors/webconsole/eager-ecma-allowlist.js
+++ b/devtools/server/actors/webconsole/eager-ecma-allowlist.js
@@ -46,7 +46,11 @@ const functionAllowList = [
Array.prototype.reduceRight,
Array.prototype.slice,
Array.prototype.some,
+ Array.prototype.toReversed,
+ Array.prototype.toSorted,
+ Array.prototype.toSpliced,
Array.prototype.values,
+ Array.prototype.with,
ArrayBuffer,
ArrayBuffer.isView,
ArrayBuffer.prototype.slice,
@@ -94,7 +98,10 @@ const functionAllowList = [
TypedArray.prototype.slice,
TypedArray.prototype.some,
TypedArray.prototype.subarray,
+ TypedArray.prototype.toReversed,
+ TypedArray.prototype.toSorted,
TypedArray.prototype.values,
+ TypedArray.prototype.with,
...allProperties(JSON),
Map,
Map.prototype.forEach,
@@ -230,20 +237,4 @@ const getterAllowList = [
getter(TypedArray, Symbol.species),
];
-// TODO: Integrate in main list when changes array by copy ships by default
-const changesArrayByCopy = [
- Array.prototype.toReversed,
- Array.prototype.toSorted,
- Array.prototype.toSpliced,
- Array.prototype.with,
- TypedArray.prototype.toReversed,
- TypedArray.prototype.toSorted,
- TypedArray.prototype.with,
-];
-for (const fn of changesArrayByCopy) {
- if (typeof fn == "function") {
- functionAllowList.push(fn);
- }
-}
-
module.exports = { functions: functionAllowList, getters: getterAllowList };
diff --git a/devtools/server/actors/webconsole/eval-with-debugger.js b/devtools/server/actors/webconsole/eval-with-debugger.js
index d422d6cd5e..34836c354f 100644
--- a/devtools/server/actors/webconsole/eval-with-debugger.js
+++ b/devtools/server/actors/webconsole/eval-with-debugger.js
@@ -8,9 +8,15 @@ const Debugger = require("Debugger");
const DevToolsUtils = require("resource://devtools/shared/DevToolsUtils.js");
const lazy = {};
-ChromeUtils.defineESModuleGetters(lazy, {
- Reflect: "resource://gre/modules/reflect.sys.mjs",
-});
+if (!isWorker) {
+ ChromeUtils.defineESModuleGetters(
+ lazy,
+ {
+ Reflect: "resource://gre/modules/reflect.sys.mjs",
+ },
+ { global: "contextual" }
+ );
+}
loader.lazyRequireGetter(
this,
["isCommand"],
@@ -600,8 +606,12 @@ function nativeIsEagerlyEvaluateable(fn) {
return true;
}
+ // This needs to use isSameNativeWithJitInfo instead of isSameNative, given
+ // DOM methods share single native function with different JSJitInto,
+ // and isSameNative cannot distinguish between side-effect-free methods
+ // and others.
const natives = gSideEffectFreeNatives.get(fn.name);
- return natives && natives.some(n => fn.isSameNative(n));
+ return natives && natives.some(n => fn.isSameNativeWithJitInfo(n));
}
function updateConsoleInputEvaluation(dbg, webConsole) {
@@ -616,7 +626,7 @@ function updateConsoleInputEvaluation(dbg, webConsole) {
}
}
-function getEvalInput(string, bindings) {
+function getEvalInput(string) {
const trimmedString = string.trim();
// Add easter egg for console.mihai().
if (
diff --git a/devtools/server/actors/webconsole/listeners/console-file-activity.js b/devtools/server/actors/webconsole/listeners/console-file-activity.js
index 7e5ae0d1a8..ccc28c3b2a 100644
--- a/devtools/server/actors/webconsole/listeners/console-file-activity.js
+++ b/devtools/server/actors/webconsole/listeners/console-file-activity.js
@@ -82,7 +82,7 @@ ConsoleFileActivityListener.prototype = {
* URI has been loaded, then the remote Web Console instance is notified.
* @private
*/
- _checkFileActivity(progress, request, state, status) {
+ _checkFileActivity(progress, request, state) {
if (!(state & Ci.nsIWebProgressListener.STATE_START)) {
return;
}
diff --git a/devtools/server/actors/webconsole/listeners/document-events.js b/devtools/server/actors/webconsole/listeners/document-events.js
index 1c1f926436..42296bf62e 100644
--- a/devtools/server/actors/webconsole/listeners/document-events.js
+++ b/devtools/server/actors/webconsole/listeners/document-events.js
@@ -90,13 +90,7 @@ DocumentEventsListener.prototype = {
});
},
- onWillNavigate({
- window,
- isTopLevel,
- newURI,
- navigationStart,
- isFrameSwitching,
- }) {
+ onWillNavigate({ isTopLevel, newURI, navigationStart, isFrameSwitching }) {
// Ignore iframes
if (!isTopLevel) {
return;
@@ -177,7 +171,7 @@ DocumentEventsListener.prototype = {
});
},
- onStateChange(progress, request, flag, status) {
+ onStateChange(progress, request, flag) {
progress.QueryInterface(Ci.nsIDocShell);
// Ignore destroyed, or progress for same-process iframes
if (progress.isBeingDestroyed() || progress != this.webProgress) {
diff --git a/devtools/server/actors/worker/service-worker-registration-list.js b/devtools/server/actors/worker/service-worker-registration-list.js
index 9821108faf..6093edc97e 100644
--- a/devtools/server/actors/worker/service-worker-registration-list.js
+++ b/devtools/server/actors/worker/service-worker-registration-list.js
@@ -5,7 +5,8 @@
"use strict";
const { XPCOMUtils } = ChromeUtils.importESModule(
- "resource://gre/modules/XPCOMUtils.sys.mjs"
+ "resource://gre/modules/XPCOMUtils.sys.mjs",
+ { global: "contextual" }
);
loader.lazyRequireGetter(
this,
@@ -102,11 +103,11 @@ class ServiceWorkerRegistrationActorList {
this._mustNotify = false;
}
- onRegister(registration) {
+ onRegister() {
this._notifyListChanged();
}
- onUnregister(registration) {
+ onUnregister() {
this._notifyListChanged();
}
}
diff --git a/devtools/server/actors/worker/service-worker-registration.js b/devtools/server/actors/worker/service-worker-registration.js
index 1e5e80ae8b..1276711191 100644
--- a/devtools/server/actors/worker/service-worker-registration.js
+++ b/devtools/server/actors/worker/service-worker-registration.js
@@ -10,7 +10,8 @@ const {
} = require("resource://devtools/shared/specs/worker/service-worker-registration.js");
const { XPCOMUtils } = ChromeUtils.importESModule(
- "resource://gre/modules/XPCOMUtils.sys.mjs"
+ "resource://gre/modules/XPCOMUtils.sys.mjs",
+ { global: "contextual" }
);
const {
PushSubscriptionActor,
@@ -210,7 +211,7 @@ class ServiceWorkerRegistrationActor extends Actor {
if (pushSubscriptionActor) {
return Promise.resolve(pushSubscriptionActor);
}
- return new Promise((resolve, reject) => {
+ return new Promise(resolve => {
PushService.getSubscription(
registration.scope,
registration.principal,
diff --git a/devtools/server/actors/worker/worker-descriptor-actor-list.js b/devtools/server/actors/worker/worker-descriptor-actor-list.js
index 10bdb5d5d3..9826791511 100644
--- a/devtools/server/actors/worker/worker-descriptor-actor-list.js
+++ b/devtools/server/actors/worker/worker-descriptor-actor-list.js
@@ -5,7 +5,8 @@
"use strict";
const { XPCOMUtils } = ChromeUtils.importESModule(
- "resource://gre/modules/XPCOMUtils.sys.mjs"
+ "resource://gre/modules/XPCOMUtils.sys.mjs",
+ { global: "contextual" }
);
loader.lazyRequireGetter(
this,