diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
commit | 40a355a42d4a9444dc753c04c6608dade2f06a23 (patch) | |
tree | 871fc667d2de662f171103ce5ec067014ef85e61 /devtools/server/actors/tracer.js | |
parent | Adding upstream version 124.0.1. (diff) | |
download | firefox-40a355a42d4a9444dc753c04c6608dade2f06a23.tar.xz firefox-40a355a42d4a9444dc753c04c6608dade2f06a23.zip |
Adding upstream version 125.0.1.upstream/125.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/server/actors/tracer.js')
-rw-r--r-- | devtools/server/actors/tracer.js | 154 |
1 files changed, 131 insertions, 23 deletions
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, |