mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
Bug 1866818 - [devtools] Enable the JS tracer on remote debugging. r=devtools-reviewers,devtools-backward-compat-reviewers,nchevobbe
Display a warning message in the tracer sidebar when there could be a backward compat issue. Differential Revision: https://phabricator.services.mozilla.com/D217745
This commit is contained in:
parent
5238055398
commit
e985b5cc50
@ -108,6 +108,8 @@ fail-if = ["a11y_checks"] # Bug 1849028 clicked element may not be focusable and
|
||||
|
||||
["browser_aboutdebugging_devtoolstoolbox_focus.js"]
|
||||
|
||||
["browser_aboutdebugging_devtoolstoolbox_jstracer.js"]
|
||||
|
||||
["browser_aboutdebugging_devtoolstoolbox_menubar.js"]
|
||||
|
||||
["browser_aboutdebugging_devtoolstoolbox_navigate_back_forward.js"]
|
||||
|
@ -0,0 +1,79 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/shared-head.js",
|
||||
this
|
||||
);
|
||||
|
||||
const TAB_URL =
|
||||
"data:text/html,<script>function foo() { bar(); }; function bar() {}</script>";
|
||||
|
||||
/* import-globals-from helper-collapsibilities.js */
|
||||
Services.scriptloader.loadSubScript(
|
||||
CHROME_URL_ROOT + "helper-collapsibilities.js",
|
||||
this
|
||||
);
|
||||
|
||||
/**
|
||||
* Test JavaScript Tracer in about:devtools-toolbox tabs (ie non localTab tab target).
|
||||
*/
|
||||
add_task(async function () {
|
||||
// This is preffed off for now, so ensure turning it on
|
||||
await pushPref("devtools.debugger.features.javascript-tracing", true);
|
||||
|
||||
const testTab = await addTab(TAB_URL);
|
||||
|
||||
info("Force all debug target panes to be expanded");
|
||||
prepareCollapsibilitiesTest();
|
||||
|
||||
const { document, tab, window } = await openAboutDebugging();
|
||||
await selectThisFirefoxPage(document, window.AboutDebugging.store);
|
||||
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox(
|
||||
document,
|
||||
tab,
|
||||
window,
|
||||
TAB_URL
|
||||
);
|
||||
info("Select performance panel");
|
||||
const toolbox = getToolbox(devtoolsWindow);
|
||||
await toolbox.selectTool("jsdebugger");
|
||||
|
||||
info("Add a breakpoint at line 10 in the test script");
|
||||
const debuggerContext = createDebuggerContext(toolbox);
|
||||
|
||||
await toggleJsTracerMenuItem(
|
||||
debuggerContext,
|
||||
"#jstracer-menu-item-debugger-sidebar"
|
||||
);
|
||||
|
||||
await toggleJsTracer(toolbox);
|
||||
|
||||
info("Invoke some code that will be traced");
|
||||
await ContentTask.spawn(testTab.linkedBrowser, {}, function () {
|
||||
content.wrappedJSObject.foo();
|
||||
});
|
||||
|
||||
info("Wait for the expected traces to appear in the call tree");
|
||||
const tree = await waitForElementWithSelector(
|
||||
debuggerContext,
|
||||
"#tracer-tab-panel .tree"
|
||||
);
|
||||
const traces = await waitFor(() => {
|
||||
const elements = tree.querySelectorAll(
|
||||
".trace-line .frame-link-function-display-name"
|
||||
);
|
||||
if (elements.length == 2) {
|
||||
return elements;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
is(traces[0].textContent, "λ foo");
|
||||
is(traces[1].textContent, "λ bar");
|
||||
|
||||
await closeAboutDevtoolsToolbox(document, devtoolsTab, window);
|
||||
await removeTab(testTab);
|
||||
await removeTab(tab);
|
||||
});
|
@ -67,3 +67,14 @@ export function selectTrace(traceIndex) {
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function setLocalAndRemoteRuntimeVersion(
|
||||
localPlatformVersion,
|
||||
remotePlatformVersion
|
||||
) {
|
||||
return {
|
||||
type: "SET_RUNTIME_VERSIONS",
|
||||
localPlatformVersion,
|
||||
remotePlatformVersion,
|
||||
};
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ import sourceQueue from "../utils/source-queue";
|
||||
const {
|
||||
TRACER_LOG_METHODS,
|
||||
} = require("resource://devtools/shared/specs/tracer.js");
|
||||
const { AppConstants } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/AppConstants.sys.mjs"
|
||||
);
|
||||
|
||||
let actions;
|
||||
let commands;
|
||||
@ -94,6 +97,15 @@ export async function onConnect(_commands, _resourceCommand, _actions, store) {
|
||||
// to be able to clear the tracer data on tracing start, that, even if the
|
||||
// tracer is waiting for next interation/load.
|
||||
commands.tracerCommand.on("toggle", onTracingToggled);
|
||||
|
||||
if (!commands.client.isLocalClient) {
|
||||
const localPlatformVersion = AppConstants.MOZ_APP_VERSION;
|
||||
const remotePlatformVersion = await getRemotePlatformVersion();
|
||||
actions.setLocalAndRemoteRuntimeVersion(
|
||||
localPlatformVersion,
|
||||
remotePlatformVersion
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function onDisconnect() {
|
||||
@ -238,4 +250,10 @@ function onDocumentEventAvailable(events) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getRemotePlatformVersion() {
|
||||
const deviceFront = await commands.client.mainRoot.getFront("device");
|
||||
const description = await deviceFront.getDescription();
|
||||
return description.platformversion;
|
||||
}
|
||||
|
||||
export { clientCommands };
|
||||
|
@ -57,6 +57,24 @@
|
||||
fill: var(--theme-icon-checked-color);
|
||||
}
|
||||
|
||||
.tracer-toolbar .tracer-runtime-version-mismatch {
|
||||
--icon-size: 16px;
|
||||
--icon-inline-padding: 4px;
|
||||
|
||||
background-color: var(--theme-warning-background);
|
||||
color: var(--theme-warning-color);
|
||||
border-block-end: 1px solid var(--theme-splitter-color);
|
||||
padding: 1em;
|
||||
padding-inline-start: calc(var(--icon-inline-padding) * 2 + var(--icon-size));
|
||||
background-image: url(resource://devtools-shared-images/alert-small.svg);
|
||||
background-position-x: var(--icon-inline-padding);
|
||||
background-position-y: 50%;
|
||||
background-repeat: no-repeat;
|
||||
background-size: var(--icon-size);
|
||||
-moz-context-properties: fill;
|
||||
fill: var(--theme-warning-color);
|
||||
}
|
||||
|
||||
.tracer-tab .tracer-message {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -20,6 +20,7 @@ import {
|
||||
getAllMutationTraces,
|
||||
getAllTraceCount,
|
||||
getIsCurrentlyTracing,
|
||||
getRuntimeVersions,
|
||||
} from "../../selectors/index";
|
||||
const VirtualizedTree = require("resource://devtools/client/shared/components/VirtualizedTree.js");
|
||||
const FrameView = createFactory(
|
||||
@ -721,6 +722,8 @@ export class Tracer extends Component {
|
||||
render() {
|
||||
const isZoomed = this.state.renderedTraceCount != this.props.traceCount;
|
||||
|
||||
const { runtimeVersions } = this.props;
|
||||
|
||||
return div(
|
||||
{
|
||||
className: "tracer-container",
|
||||
@ -738,6 +741,16 @@ export class Tracer extends Component {
|
||||
"This panel is experimental. It may change, regress, be dropped or replaced."
|
||||
)
|
||||
: null,
|
||||
runtimeVersions &&
|
||||
runtimeVersions.localPlatformVersion !=
|
||||
runtimeVersions.remotePlatformVersion
|
||||
? div(
|
||||
{
|
||||
className: "tracer-runtime-version-mismatch",
|
||||
},
|
||||
`Client and remote runtime have different versions (${runtimeVersions.localPlatformVersion} vs ${runtimeVersions.remotePlatformVersion}) . The Tracer may be broken because of protocol changes between these two versions. Please upgrade or downgrade one of the two to use the same major version.`
|
||||
)
|
||||
: null,
|
||||
this.renderSearchInput()
|
||||
),
|
||||
isZoomed
|
||||
@ -830,6 +843,7 @@ const mapStateToProps = state => {
|
||||
mutationTraces: getAllMutationTraces(state),
|
||||
traceCount: getAllTraceCount(state),
|
||||
selectedTraceIndex: getSelectedTraceIndex(state),
|
||||
runtimeVersions: getRuntimeVersions(state),
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -30,6 +30,10 @@ function initialState() {
|
||||
|
||||
// Index of the currently selected trace within `mutableTraces`.
|
||||
selectedTraceIndex: null,
|
||||
|
||||
// Runtime versions to help show warning when there is a mismatch between frontend and backend versions
|
||||
localPlatformVersion: null,
|
||||
remotePlatformVersion: null,
|
||||
};
|
||||
}
|
||||
|
||||
@ -127,6 +131,13 @@ function update(state = initialState(), action) {
|
||||
selectedTrace: null,
|
||||
};
|
||||
}
|
||||
case "SET_RUNTIME_VERSIONS": {
|
||||
return {
|
||||
...state,
|
||||
localPlatformVersion: action.localPlatformVersion,
|
||||
remotePlatformVersion: action.remotePlatformVersion,
|
||||
};
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -26,3 +26,9 @@ export function getAllMutationTraces(state) {
|
||||
export function getAllTraceCount(state) {
|
||||
return state.tracerFrames?.mutableTraces.length || 0;
|
||||
}
|
||||
export function getRuntimeVersions(state) {
|
||||
return {
|
||||
localPlatformVersion: state.tracerFrames?.localPlatformVersion,
|
||||
remotePlatformVersion: state.tracerFrames?.remotePlatformVersion,
|
||||
};
|
||||
}
|
||||
|
@ -619,9 +619,7 @@ exports.ToolboxButtons = [
|
||||
"toolbox.buttons.jstracer",
|
||||
osString == "Darwin" ? "Cmd+Shift+5" : "Ctrl+Shift+5"
|
||||
),
|
||||
isToolSupported: toolbox =>
|
||||
(toolbox.commands.descriptorFront.isLocalTab ||
|
||||
toolbox.isBrowserToolbox) &&
|
||||
isToolSupported: () =>
|
||||
Services.prefs.getBoolPref(
|
||||
"devtools.debugger.features.javascript-tracing",
|
||||
false
|
||||
|
@ -792,6 +792,14 @@ DevToolsClient.prototype = {
|
||||
return this._transport;
|
||||
},
|
||||
|
||||
/**
|
||||
* Boolean flag to help identify client connected to the current runtime,
|
||||
* via a LocalDevToolsTransport pipe.
|
||||
*/
|
||||
get isLocalClient() {
|
||||
return !!this._transport.isLocalTransport;
|
||||
},
|
||||
|
||||
dumpPools() {
|
||||
for (const pool of this._pools) {
|
||||
console.log(`%c${pool.actorID}`, "font-weight: bold;", [
|
||||
|
@ -241,6 +241,9 @@ const BOOLEAN_CONFIGURATION_PREFS = {
|
||||
name: "pauseOverlay",
|
||||
thread: true,
|
||||
},
|
||||
"devtools.debugger.features.javascript-tracing": {
|
||||
name: "isTracerFeatureEnabled",
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2392,12 +2392,36 @@ async function unregisterServiceWorker(workerUrl) {
|
||||
* Toggle the JavavaScript tracer via its toolbox toolbar button.
|
||||
*/
|
||||
async function toggleJsTracer(toolbox) {
|
||||
const { isTracingEnabled } = toolbox.commands.tracerCommand;
|
||||
const { tracerCommand } = toolbox.commands;
|
||||
const { isTracingEnabled } = tracerCommand;
|
||||
const { logMethod, traceOnNextInteraction, traceOnNextLoad } =
|
||||
toolbox.commands.tracerCommand.getTracingOptions();
|
||||
|
||||
// When the tracer is waiting for user interaction or page load, it won't be made active
|
||||
// right away. The test should manually wait for its activation.
|
||||
const shouldWaitForToggle = !traceOnNextInteraction && !traceOnNextLoad;
|
||||
let onTracingToggled;
|
||||
if (shouldWaitForToggle) {
|
||||
onTracingToggled = new Promise(resolve => {
|
||||
tracerCommand.on("toggle", async function listener() {
|
||||
// Ignore the event, if we are still in the same state as before the click
|
||||
if (tracerCommand.isTracingActive == isTracingEnabled) {
|
||||
return;
|
||||
}
|
||||
tracerCommand.off("toggle", listener);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const toolbarButton = toolbox.doc.getElementById("command-button-jstracer");
|
||||
toolbarButton.click();
|
||||
|
||||
if (shouldWaitForToggle) {
|
||||
info("Waiting for the tracer to be active");
|
||||
await onTracingToggled;
|
||||
}
|
||||
|
||||
const {
|
||||
TRACER_LOG_METHODS,
|
||||
} = require("resource://devtools/shared/specs/tracer.js");
|
||||
|
@ -31,6 +31,8 @@ const SUPPORTED_OPTIONS = {
|
||||
customFormatters: true,
|
||||
// Set a custom user agent
|
||||
customUserAgent: true,
|
||||
// Is the tracer experimental feature manually enabled by the user?
|
||||
isTracerFeatureEnabled: true,
|
||||
// Enable JavaScript
|
||||
javascriptEnabled: true,
|
||||
// Force a custom device pixel ratio (used in RDM). Set to null to restore origin ratio.
|
||||
|
@ -224,6 +224,14 @@ class BaseTargetActor extends Actor {
|
||||
return this.#instantiatedTargetScopedActors.has(prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Server side boolean to know if the tracer has been enabled by the user.
|
||||
*
|
||||
* By enabled, we mean the feature has been exposed to the user,
|
||||
* not that the tracer is actively tracing executions.
|
||||
*/
|
||||
isTracerFeatureEnabled = false;
|
||||
|
||||
/**
|
||||
* Apply target-specific options.
|
||||
*
|
||||
@ -238,6 +246,9 @@ class BaseTargetActor extends Actor {
|
||||
* actor is instantiated.
|
||||
*/
|
||||
updateTargetConfiguration(options = {}, calledFromDocumentCreation = false) {
|
||||
if (typeof options.isTracerFeatureEnabled === "boolean") {
|
||||
this.isTracerFeatureEnabled = options.isTracerFeatureEnabled;
|
||||
}
|
||||
// If there is some tracer options, we should start tracing, otherwise we should stop (if we were)
|
||||
if (options.tracerOptions) {
|
||||
// Ignore the SessionData update if the user requested to start the tracer on next page load and:
|
||||
|
@ -866,16 +866,12 @@ WebConsoleCommandsManager.register({
|
||||
name: "trace",
|
||||
isSideEffectFree: false,
|
||||
command(owner, args) {
|
||||
// Disable :trace command on worker until this feature is enabled by default
|
||||
if (isWorker) {
|
||||
throw new Error(":trace command isn't supported in workers");
|
||||
}
|
||||
// Disable :trace command on worker until this feature is enabled by default
|
||||
if (
|
||||
!Services.prefs.getBoolPref(
|
||||
"devtools.debugger.features.javascript-tracing",
|
||||
false
|
||||
)
|
||||
) {
|
||||
|
||||
if (!owner.consoleActor.parentActor.isTracerFeatureEnabled) {
|
||||
throw new Error(
|
||||
":trace requires 'devtools.debugger.features.javascript-tracing' preference to be true"
|
||||
);
|
||||
|
@ -25,6 +25,7 @@ types.addDictType("target-configuration.configuration", {
|
||||
serviceWorkersTestingEnabled: "nullable:boolean",
|
||||
setTabOffline: "nullable:boolean",
|
||||
touchEventsOverride: "nullable:string",
|
||||
isTracerFeatureEnabled: "nullable:boolean",
|
||||
});
|
||||
|
||||
const targetConfigurationSpec = generateActorSpec({
|
||||
|
@ -35,6 +35,12 @@ function LocalDebuggerTransport(other) {
|
||||
}
|
||||
|
||||
LocalDebuggerTransport.prototype = {
|
||||
/**
|
||||
* Boolean to help identify DevToolsClient instances connected to a LocalDevToolsTransport pipe
|
||||
* and so connected to the same runtime as the frontend.
|
||||
*/
|
||||
isLocalTransport: true,
|
||||
|
||||
/**
|
||||
* Transmit a message by directly calling the onPacket handler of the other
|
||||
* endpoint.
|
||||
|
Loading…
Reference in New Issue
Block a user