1
0
Fork 0
firefox/devtools/server/actors/tracer/profiler.js
Daniel Baumann 5e9a113729
Adding upstream version 140.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-25 09:37:52 +02:00

129 lines
4.3 KiB
JavaScript

/* 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";
// The functions in the class use standard functions called from tracer.js but we want to keep the
// arguments intact.
/* eslint "no-unused-vars": ["error", {args: "none"} ]*/
class ProfilerTracingListener {
constructor({ targetActor, traceActor }) {
this.targetActor = targetActor;
this.traceActor = traceActor;
}
/**
* Stop the record and return the gecko profiler data.
*
* @param {Object} nativeTrace
* If we're using native tracing, this contains a table of what the
* native tracer has collected.
* @return {Object}
* The Gecko profile object.
*/
async stop(nativeTrace) {
// Pause profiler before we collect the profile, so that we don't capture
// more samples while the parent process or android threads wait for subprocess profiles.
Services.profiler.Pause();
let profile;
try {
// Attempt to pull out the data.
profile = await Services.profiler.getProfileDataAsync();
if (Object.keys(profile).length === 0) {
console.error(
"An empty object was received from getProfileDataAsync.getProfileDataAsync(), " +
"meaning that a profile could not successfully be serialized and captured."
);
profile = null;
}
} catch (e) {
// Explicitly set the profile to null if there as an error.
profile = null;
console.error(`There was an error fetching a profile`, e);
}
Services.profiler.StopProfiler();
return profile;
}
/**
* Be notified by the underlying JavaScriptTracer class
* in case it stops by itself, instead of being stopped when the Actor's stopTracing
* method is called by the user.
*
* @param {Boolean} enabled
* True if the tracer starts tracing, false it it stops.
* @return {Boolean}
* Return true, if the JavaScriptTracer should log a message to stdout.
*/
onTracingToggled(enabled) {
if (!enabled) {
this.traceActor.stopTracing();
} else {
Services.profiler.StartProfiler(
// Note that this is the same default as profiler ones defined in:
// devtools/client/performance-new/shared/background.sys.mjs
128 * 1024 * 1024,
1,
["screenshots", "tracing"],
["GeckoMain", "DOM Worker"],
this.targetActor.sessionContext.browserId,
0
);
}
return false;
}
/**
* Called when "trace on next user interaction" is enabled, to notify the user
* that the tracer is initialized but waiting for the user first input.
*/
onTracingPending() {
return false;
}
/**
* 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.
* @return {Boolean}
* Return true, if the JavaScriptTracer should log a message to stdout.
*/
onTracingDOMMutation({ depth, prefix, type, caller, element }) {
let elementDescription = element.tagName?.toLowerCase();
if (element.id) {
elementDescription += `#${element.id}`;
}
if (element.className) {
elementDescription += `.${element.className.trim().replace(/ +/g, ".")}`;
}
const description = `${type} on ${elementDescription}`;
// Bug 1904602: we need a tweak in profiler frontend before being able to show
// dom mutation in the stack chart. Until then, add a custom marker.
ChromeUtils.addProfilerMarker("DOM-Mutation", undefined, description);
return false;
}
}
exports.ProfilerTracingListener = ProfilerTracingListener;