Source code

Revision control

Copy as Markdown

Other Tools

/* 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 EventEmitter = require("resource://devtools/shared/event-emitter.js");
loader.lazyRequireGetter(
this,
"TRACER_LOG_METHODS",
"resource://devtools/shared/specs/tracer.js",
true
);
class TracerCommand extends EventEmitter {
constructor({ commands }) {
super();
this.#targetConfigurationCommand = commands.targetConfigurationCommand;
this.#resourceCommand = commands.resourceCommand;
}
// The tracer has been requested to start, but doesn't necessarily mean it actually started tracing JS executions.
// The tracer may wait for next user interaction/document load before being active.
isTracingEnabled = false;
// The tracer is actively tracking JS executions.
isTracingActive = false;
#resourceCommand;
#targetConfigurationCommand;
async initialize() {
return this.#resourceCommand.watchResources(
[this.#resourceCommand.TYPES.JSTRACER_STATE],
{ onAvailable: this.onResourcesAvailable }
);
}
destroy() {
this.#resourceCommand.unwatchResources(
[this.#resourceCommand.TYPES.JSTRACER_STATE],
{ onAvailable: this.onResourcesAvailable }
);
}
onResourcesAvailable = resources => {
for (const resource of resources) {
if (resource.resourceType != this.#resourceCommand.TYPES.JSTRACER_STATE) {
continue;
}
// Clear the list of collected frames each time we start a new tracer record.
// The tracer will reset its frame counter to zero on stop, but on the frontend
// we may inspect frames after the tracer is stopped, until we start a new one.
if (resource.enabled) {
resource.targetFront.getJsTracerCollectedFramesArray().length = 0;
}
if (
resource.enabled == this.isTracingActive &&
resource.enabled == this.isTracingEnabled
) {
continue;
}
this.isTracingActive = resource.enabled;
// In case the tracer is started without the DevTools frontend, also force it to be reported as enabled
this.isTracingEnabled = resource.enabled;
this.emit("toggle");
}
};
/**
* Get the dictionary passed to the server codebase as a SessionData.
* This contains all settings to fine tune the tracer actual behavior.
*
* @return {JSON}
* Configuration object.
*/
getTracingOptions() {
const logMethod = Services.prefs.getStringPref(
"devtools.debugger.javascript-tracing-log-method",
""
);
return {
logMethod,
// Force enabling DOM Mutation logging as soon as we selected the sidebar log output
traceDOMMutations:
logMethod == TRACER_LOG_METHODS.DEBUGGER_SIDEBAR
? ["add", "attributes", "remove"]
: null,
traceValues: Services.prefs.getBoolPref(
"devtools.debugger.javascript-tracing-values",
false
),
traceOnNextInteraction: Services.prefs.getBoolPref(
"devtools.debugger.javascript-tracing-on-next-interaction",
false
),
traceOnNextLoad: Services.prefs.getBoolPref(
"devtools.debugger.javascript-tracing-on-next-load",
false
),
traceFunctionReturn: Services.prefs.getBoolPref(
"devtools.debugger.javascript-tracing-function-return",
false
),
};
}
/**
* Toggle JavaScript tracing for all targets.
*/
async toggle() {
this.isTracingEnabled = !this.isTracingEnabled;
// May be wait for the web console to be fully initialized and listening to tracer resources before enabling it
await this.emitAsync("toggle");
await this.#targetConfigurationCommand.updateConfiguration({
tracerOptions: this.isTracingEnabled
? this.getTracingOptions()
: undefined,
});
}
}
module.exports = TracerCommand;