summaryrefslogtreecommitdiffstats
path: root/devtools/client/performance/modules/marker-formatters.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/performance/modules/marker-formatters.js')
-rw-r--r--devtools/client/performance/modules/marker-formatters.js199
1 files changed, 199 insertions, 0 deletions
diff --git a/devtools/client/performance/modules/marker-formatters.js b/devtools/client/performance/modules/marker-formatters.js
new file mode 100644
index 000000000..0d74913cc
--- /dev/null
+++ b/devtools/client/performance/modules/marker-formatters.js
@@ -0,0 +1,199 @@
+/* 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";
+
+/**
+ * This file contains utilities for creating elements for markers to be displayed,
+ * and parsing out the blueprint to generate correct values for markers.
+ */
+const { Ci } = require("chrome");
+const { L10N, PREFS } = require("devtools/client/performance/modules/global");
+
+// String used to fill in platform data when it should be hidden.
+const GECKO_SYMBOL = "(Gecko)";
+
+/**
+ * Mapping of JS marker causes to a friendlier form. Only
+ * markers that are considered "from content" should be labeled here.
+ */
+const JS_MARKER_MAP = {
+ "<script> element": L10N.getStr("marker.label.javascript.scriptElement"),
+ "promise callback": L10N.getStr("marker.label.javascript.promiseCallback"),
+ "promise initializer": L10N.getStr("marker.label.javascript.promiseInit"),
+ "Worker runnable": L10N.getStr("marker.label.javascript.workerRunnable"),
+ "javascript: URI": L10N.getStr("marker.label.javascript.jsURI"),
+ // The difference between these two event handler markers are differences
+ // in their WebIDL implementation, so distinguishing them is not necessary.
+ "EventHandlerNonNull": L10N.getStr("marker.label.javascript.eventHandler"),
+ "EventListener.handleEvent": L10N.getStr("marker.label.javascript.eventHandler"),
+ // These markers do not get L10N'd because they're JS names.
+ "setInterval handler": "setInterval",
+ "setTimeout handler": "setTimeout",
+ "FrameRequestCallback": "requestAnimationFrame",
+};
+
+/**
+ * A series of formatters used by the blueprint.
+ */
+exports.Formatters = {
+ /**
+ * Uses the marker name as the label for markers that do not have
+ * a blueprint entry. Uses "Other" in the marker filter menu.
+ */
+ UnknownLabel: function (marker = {}) {
+ return marker.name || L10N.getStr("marker.label.unknown");
+ },
+
+ /* Group 0 - Reflow and Rendering pipeline */
+
+ StylesFields: function (marker) {
+ if ("restyleHint" in marker) {
+ let label = marker.restyleHint.replace(/eRestyle_/g, "");
+ return {
+ [L10N.getStr("marker.field.restyleHint")]: label
+ };
+ }
+ return null;
+ },
+
+ /* Group 1 - JS */
+
+ DOMEventFields: function (marker) {
+ let fields = Object.create(null);
+
+ if ("type" in marker) {
+ fields[L10N.getStr("marker.field.DOMEventType")] = marker.type;
+ }
+
+ if ("eventPhase" in marker) {
+ let label;
+ switch (marker.eventPhase) {
+ case Ci.nsIDOMEvent.AT_TARGET:
+ label = L10N.getStr("marker.value.DOMEventTargetPhase");
+ break;
+ case Ci.nsIDOMEvent.CAPTURING_PHASE:
+ label = L10N.getStr("marker.value.DOMEventCapturingPhase");
+ break;
+ case Ci.nsIDOMEvent.BUBBLING_PHASE:
+ label = L10N.getStr("marker.value.DOMEventBubblingPhase");
+ break;
+ }
+ fields[L10N.getStr("marker.field.DOMEventPhase")] = label;
+ }
+
+ return fields;
+ },
+
+ JSLabel: function (marker = {}) {
+ let generic = L10N.getStr("marker.label.javascript");
+ if ("causeName" in marker) {
+ return JS_MARKER_MAP[marker.causeName] || generic;
+ }
+ return generic;
+ },
+
+ JSFields: function (marker) {
+ if ("causeName" in marker && !JS_MARKER_MAP[marker.causeName]) {
+ let label = PREFS["show-platform-data"] ? marker.causeName : GECKO_SYMBOL;
+ return {
+ [L10N.getStr("marker.field.causeName")]: label
+ };
+ }
+ return null;
+ },
+
+ GCLabel: function (marker) {
+ if (!marker) {
+ return L10N.getStr("marker.label.garbageCollection2");
+ }
+ // Only if a `nonincrementalReason` exists, do we want to label
+ // this as a non incremental GC event.
+ if ("nonincrementalReason" in marker) {
+ return L10N.getStr("marker.label.garbageCollection.nonIncremental");
+ }
+ return L10N.getStr("marker.label.garbageCollection.incremental");
+ },
+
+ GCFields: function (marker) {
+ let fields = Object.create(null);
+
+ if ("causeName" in marker) {
+ let cause = marker.causeName;
+ let label = L10N.getStr(`marker.gcreason.label.${cause}`) || cause;
+ fields[L10N.getStr("marker.field.causeName")] = label;
+ }
+
+ if ("nonincrementalReason" in marker) {
+ let label = marker.nonincrementalReason;
+ fields[L10N.getStr("marker.field.nonIncrementalCause")] = label;
+ }
+
+ return fields;
+ },
+
+ MinorGCFields: function (marker) {
+ let fields = Object.create(null);
+
+ if ("causeName" in marker) {
+ let cause = marker.causeName;
+ let label = L10N.getStr(`marker.gcreason.label.${cause}`) || cause;
+ fields[L10N.getStr("marker.field.causeName")] = label;
+ }
+
+ fields[L10N.getStr("marker.field.type")] = L10N.getStr("marker.nurseryCollection");
+
+ return fields;
+ },
+
+ CycleCollectionFields: function (marker) {
+ let label = marker.name.replace(/nsCycleCollector::/g, "");
+ return {
+ [L10N.getStr("marker.field.type")]: label
+ };
+ },
+
+ WorkerFields: function (marker) {
+ if ("workerOperation" in marker) {
+ let label = L10N.getStr(`marker.worker.${marker.workerOperation}`);
+ return {
+ [L10N.getStr("marker.field.type")]: label
+ };
+ }
+ return null;
+ },
+
+ MessagePortFields: function (marker) {
+ if ("messagePortOperation" in marker) {
+ let label = L10N.getStr(`marker.messagePort.${marker.messagePortOperation}`);
+ return {
+ [L10N.getStr("marker.field.type")]: label
+ };
+ }
+ return null;
+ },
+
+ /* Group 2 - User Controlled */
+
+ ConsoleTimeFields: {
+ [L10N.getStr("marker.field.consoleTimerName")]: "causeName"
+ },
+
+ TimeStampFields: {
+ [L10N.getStr("marker.field.label")]: "causeName"
+ }
+};
+
+/**
+ * Takes a main label (e.g. "Timestamp") and a property name (e.g. "causeName"),
+ * and returns a string that represents that property value for a marker if it
+ * exists (e.g. "Timestamp (rendering)"), or just the main label if it does not.
+ *
+ * @param string mainLabel
+ * @param string propName
+ */
+exports.Formatters.labelForProperty = function (mainLabel, propName) {
+ return (marker = {}) => marker[propName]
+ ? `${mainLabel} (${marker[propName]})`
+ : mainLabel;
+};