mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge fx-team to mozilla-central a=merge
This commit is contained in:
commit
b4eb63ff3e
@ -1455,6 +1455,13 @@ pref("devtools.performance.ui.enable-memory", false);
|
||||
pref("devtools.performance.ui.enable-framerate", true);
|
||||
pref("devtools.performance.ui.show-jit-optimizations", false);
|
||||
|
||||
// Enable experimental options in the UI only in Nightly
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
pref("devtools.performance.ui.experimental", true);
|
||||
#else
|
||||
pref("devtools.performance.ui.experimental", false);
|
||||
#endif
|
||||
|
||||
// The default cache UI setting
|
||||
pref("devtools.cache.disabled", false);
|
||||
|
||||
|
@ -427,6 +427,7 @@ skip-if = e10s # Bug 1100700 - test relies on unload event firing on closed tabs
|
||||
[browser_urlHighlight.js]
|
||||
[browser_urlbarAutoFillTrimURLs.js]
|
||||
[browser_urlbarCopying.js]
|
||||
[browser_urlbarDelete.js]
|
||||
[browser_urlbarEnter.js]
|
||||
[browser_urlbarEnterAfterMouseOver.js]
|
||||
skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
|
||||
|
53
browser/base/content/test/general/browser_urlbarDelete.js
Normal file
53
browser/base/content/test/general/browser_urlbarDelete.js
Normal file
@ -0,0 +1,53 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
add_task(function*() {
|
||||
let bm = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.com/",
|
||||
title: "test" });
|
||||
|
||||
registerCleanupFunction(function* () {
|
||||
yield PlacesUtils.bookmarks.remove(bm);
|
||||
});
|
||||
|
||||
// We do this test with both unifiedcomplete disabled and enabled.
|
||||
let ucpref = Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete");
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.setBoolPref("browser.urlbar.unifiedcomplete", ucpref);
|
||||
});
|
||||
|
||||
Services.prefs.setBoolPref("browser.urlbar.unifiedcomplete", false);
|
||||
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, testDelete);
|
||||
|
||||
Services.prefs.setBoolPref("browser.urlbar.unifiedcomplete", true);
|
||||
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, testDelete);
|
||||
});
|
||||
|
||||
function sendHome() {
|
||||
// unclear why VK_HOME doesn't work on Mac, but it doesn't...
|
||||
if (Services.appinfo.OS == "Darwin") {
|
||||
EventUtils.synthesizeKey("VK_LEFT", { altKey: true });
|
||||
} else {
|
||||
EventUtils.synthesizeKey("VK_HOME", {});
|
||||
}
|
||||
}
|
||||
|
||||
function sendDelete() {
|
||||
EventUtils.synthesizeKey("VK_DELETE", {});
|
||||
}
|
||||
|
||||
function* testDelete() {
|
||||
yield promiseAutocompleteResultPopup("exam");
|
||||
|
||||
// move to the start.
|
||||
sendHome();
|
||||
// delete the first few chars - each delete should operate on the input field.
|
||||
sendDelete();
|
||||
Assert.equal(gURLBar.inputField.value, "xam");
|
||||
|
||||
yield promisePopupShown(gURLBar.popup);
|
||||
|
||||
sendDelete();
|
||||
Assert.equal(gURLBar.inputField.value, "am");
|
||||
}
|
@ -866,6 +866,23 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="handleDelete">
|
||||
<body><![CDATA[
|
||||
// When UnifiedComplete is enabled, we arrange for the popup to
|
||||
// always have a "special" first item that's always selected. The
|
||||
// autocomplete controller's handleDelete() implementation will
|
||||
// remove the selected entry from the popup in that case.
|
||||
// So when our first special item is selected, we call handleText
|
||||
// instead so it acts as a delete on the text value instead of
|
||||
// removing that item.
|
||||
if (Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete") &&
|
||||
this.popup.selectedIndex == 0) {
|
||||
return this.mController.handleText();
|
||||
}
|
||||
return this.mController.handleDelete();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
|
@ -100,6 +100,7 @@ browser.jar:
|
||||
content/browser/devtools/webaudioeditor/views/properties.js (webaudioeditor/views/properties.js)
|
||||
content/browser/devtools/webaudioeditor/views/automation.js (webaudioeditor/views/automation.js)
|
||||
content/browser/devtools/performance.xul (performance/performance.xul)
|
||||
* content/browser/devtools/performance/system.js (performance/system.js)
|
||||
content/browser/devtools/performance/performance-controller.js (performance/performance-controller.js)
|
||||
content/browser/devtools/performance/performance-view.js (performance/performance-view.js)
|
||||
content/browser/devtools/performance/views/overview.js (performance/views/overview.js)
|
||||
|
@ -209,7 +209,9 @@ exports.RecordingUtils.getProfileThreadFromAllocations = function(allocations) {
|
||||
* The filtered timeline blueprint.
|
||||
*/
|
||||
exports.RecordingUtils.getFilteredBlueprint = function({ blueprint, hiddenMarkers }) {
|
||||
let filteredBlueprint = Cu.cloneInto(blueprint, {});
|
||||
// Clone functions here just to prevent an error, as the blueprint
|
||||
// contains functions (even though we do not use them).
|
||||
let filteredBlueprint = Cu.cloneInto(blueprint, {}, { cloneFunctions: true });
|
||||
let maybeRemovedGroups = new Set();
|
||||
let removedGroups = new Set();
|
||||
|
||||
|
@ -191,6 +191,11 @@ let PerformanceController = {
|
||||
this._onRecordingStateChange = this._onRecordingStateChange.bind(this);
|
||||
this._onProfilerStatusUpdated = this._onProfilerStatusUpdated.bind(this);
|
||||
|
||||
// Store data regarding if e10s is enabled.
|
||||
this._e10s = Services.appinfo.browserTabsRemoteAutostart;
|
||||
|
||||
this._setMultiprocessAttributes();
|
||||
|
||||
// All boolean prefs should be handled via the OptionsView in the
|
||||
// ToolbarView, so that they may be accessible via the "gear" menu.
|
||||
// Every other pref should be registered here.
|
||||
@ -513,6 +518,44 @@ let PerformanceController = {
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an object with `supported` and `enabled` properties indicating
|
||||
* whether or not the platform is capable of turning on e10s and whether or not
|
||||
* it's already enabled, respectively.
|
||||
*
|
||||
* @return {object}
|
||||
*/
|
||||
getMultiprocessStatus: function () {
|
||||
// If testing, set both supported and enabled to true so we
|
||||
// have realtime rendering tests in non-e10s. This function is
|
||||
// overridden wholesale in tests when we want to test multiprocess support
|
||||
// specifically.
|
||||
if (gDevTools.testing) {
|
||||
return { supported: true, enabled: true };
|
||||
}
|
||||
let supported = SYSTEM.MULTIPROCESS_SUPPORTED;
|
||||
// This is only checked on tool startup -- requires a restart if
|
||||
// e10s subsequently enabled.
|
||||
let enabled = this._e10s;
|
||||
return { supported, enabled };
|
||||
},
|
||||
|
||||
/**
|
||||
* Called on init, sets an `e10s` attribute on the main view container with
|
||||
* "disabled" if e10s is possible on the platform and just not on, or "unsupported"
|
||||
* if e10s is not possible on the platform. If e10s is on, no attribute is set.
|
||||
*/
|
||||
_setMultiprocessAttributes: function () {
|
||||
let { enabled, supported } = this.getMultiprocessStatus();
|
||||
if (!enabled && supported) {
|
||||
$("#performance-view").setAttribute("e10s", "disabled");
|
||||
}
|
||||
// Could be a chance where the directive goes away yet e10s is still on
|
||||
else if (!enabled && !supported) {
|
||||
$("#performance-view").setAttribute("e10s", "unsupported");
|
||||
}
|
||||
},
|
||||
|
||||
toString: () => "[object PerformanceController]"
|
||||
};
|
||||
|
||||
|
@ -30,6 +30,10 @@ let PerformanceView = {
|
||||
recorded: [
|
||||
{ deck: "#performance-view", pane: "#performance-view-content" },
|
||||
{ deck: "#details-pane-container", pane: "#details-pane" }
|
||||
],
|
||||
loading: [
|
||||
{ deck: "#performance-view", pane: "#performance-view-content" },
|
||||
{ deck: "#details-pane-container", pane: "#loading-notice" }
|
||||
]
|
||||
},
|
||||
|
||||
@ -50,6 +54,7 @@ let PerformanceView = {
|
||||
this._onRecordingStopped = this._onRecordingStopped.bind(this);
|
||||
this._onRecordingStarted = this._onRecordingStarted.bind(this);
|
||||
this._onProfilerStatusUpdated = this._onProfilerStatusUpdated.bind(this);
|
||||
this._onRecordingWillStop = this._onRecordingWillStop.bind(this);
|
||||
|
||||
for (let button of $$(".record-button")) {
|
||||
button.addEventListener("click", this._onRecordButtonClick);
|
||||
@ -62,6 +67,7 @@ let PerformanceView = {
|
||||
PerformanceController.on(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
|
||||
PerformanceController.on(EVENTS.RECORDING_SELECTED, this._onRecordingSelected);
|
||||
PerformanceController.on(EVENTS.PROFILER_STATUS_UPDATED, this._onProfilerStatusUpdated);
|
||||
PerformanceController.on(EVENTS.RECORDING_WILL_STOP, this._onRecordingWillStop);
|
||||
|
||||
this.setState("empty");
|
||||
|
||||
@ -87,6 +93,7 @@ let PerformanceView = {
|
||||
PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
|
||||
PerformanceController.off(EVENTS.RECORDING_SELECTED, this._onRecordingSelected);
|
||||
PerformanceController.off(EVENTS.PROFILER_STATUS_UPDATED, this._onProfilerStatusUpdated);
|
||||
PerformanceController.off(EVENTS.RECORDING_WILL_STOP, this._onRecordingWillStop);
|
||||
|
||||
yield ToolbarView.destroy();
|
||||
yield RecordingsView.destroy();
|
||||
@ -218,6 +225,17 @@ let PerformanceView = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fired when a recording is stopping, but not yet completed
|
||||
*/
|
||||
_onRecordingWillStop: function (_, recording) {
|
||||
// Lock the details view while the recording is being loaded in the UI.
|
||||
// Only do this if this is the current recording.
|
||||
if (recording === PerformanceController.getCurrentRecording()) {
|
||||
this.setState("loading");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for clicking the clear button.
|
||||
*/
|
||||
@ -249,7 +267,8 @@ let PerformanceView = {
|
||||
*/
|
||||
_onImportButtonClick: function(e) {
|
||||
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
||||
fp.init(window, L10N.getStr("recordingsList.saveDialogTitle"), Ci.nsIFilePicker.modeOpen);
|
||||
// TODO localize? in bug 1163763
|
||||
fp.init(window, "Import recording…", Ci.nsIFilePicker.modeOpen);
|
||||
fp.appendFilter(L10N.getStr("recordingsList.saveDialogJSONFilter"), "*.json");
|
||||
fp.appendFilter(L10N.getStr("recordingsList.saveDialogAllFilter"), "*.*");
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="chrome://browser/content/devtools/theme-switching.js"/>
|
||||
<script type="application/javascript" src="performance/system.js"/>
|
||||
<script type="application/javascript" src="performance/performance-controller.js"/>
|
||||
<script type="application/javascript" src="performance/performance-view.js"/>
|
||||
<script type="application/javascript" src="performance/recording-model.js"/>
|
||||
@ -37,12 +38,12 @@
|
||||
data-pref="show-platform-data"
|
||||
label="&profilerUI.showPlatformData;"
|
||||
tooltiptext="&profilerUI.showPlatformData.tooltiptext;"/>
|
||||
<!-- TODO Re-enable in bug 1163350 -->
|
||||
<!-- <menuitem id="option-enable-memory"
|
||||
<menuitem id="option-enable-memory"
|
||||
class="experimental-option"
|
||||
type="checkbox"
|
||||
data-pref="enable-memory"
|
||||
label="&profilerUI.enableMemory;"
|
||||
tooltiptext="&profilerUI.enableMemory.tooltiptext;"/> -->
|
||||
tooltiptext="&profilerUI.enableMemory.tooltiptext;"/>
|
||||
<menuitem id="option-enable-framerate"
|
||||
type="checkbox"
|
||||
data-pref="enable-framerate"
|
||||
@ -63,12 +64,12 @@
|
||||
data-pref="flatten-tree-recursion"
|
||||
label="&profilerUI.flattenTreeRecursion;"
|
||||
tooltiptext="&profilerUI.flattenTreeRecursion.tooltiptext;"/>
|
||||
<!-- TODO Re-enable in bug 1163351 -->
|
||||
<!-- <menuitem id="option-show-jit-optimizations"
|
||||
<menuitem id="option-show-jit-optimizations"
|
||||
class="experimental-option"
|
||||
type="checkbox"
|
||||
data-pref="show-jit-optimizations"
|
||||
label="&profilerUI.showJITOptimizations;"
|
||||
tooltiptext="&profilerUI.showJITOptimizations.tooltiptext;"/> -->
|
||||
tooltiptext="&profilerUI.showJITOptimizations.tooltiptext;"/>
|
||||
</menupopup>
|
||||
</popupset>
|
||||
|
||||
@ -96,8 +97,8 @@
|
||||
<toolbar id="performance-toolbar" class="devtools-toolbar">
|
||||
<hbox id="performance-toolbar-control-other" class="devtools-toolbarbutton-group">
|
||||
<toolbarbutton id="filter-button"
|
||||
popup="performance-filter-menupopup"
|
||||
class="devtools-toolbarbutton"
|
||||
popup="performance-filter-menupopup"
|
||||
tooltiptext="&profilerUI.options.filter.tooltiptext;"/>
|
||||
</hbox>
|
||||
<hbox id="performance-toolbar-controls-detail-views" class="devtools-toolbarbutton-group">
|
||||
@ -155,6 +156,13 @@
|
||||
<hbox id="time-framerate"/>
|
||||
</vbox>
|
||||
<deck id="details-pane-container" flex="1">
|
||||
<hbox id="loading-notice"
|
||||
class="notice-container devtools-throbber"
|
||||
align="center"
|
||||
pack="center"
|
||||
flex="1">
|
||||
<label value="&profilerUI.loadingNotice;"/>
|
||||
</hbox>
|
||||
<hbox id="recording-notice"
|
||||
class="notice-container"
|
||||
align="center"
|
||||
@ -166,6 +174,10 @@
|
||||
<toolbarbutton class="devtools-toolbarbutton record-button"
|
||||
label="&profilerUI.stopRecording;" />
|
||||
</hbox>
|
||||
<label class="realtime-disabled-message"
|
||||
value="Realtime recording data disabled on non-multiprocess Firefox."/>
|
||||
<label class="realtime-disabled-on-e10s-message"
|
||||
value="Enable multiprocess Firefox in preferences for rendering recording data in realtime."/>
|
||||
<label class="buffer-status-message"
|
||||
tooltiptext="&profilerUI.bufferStatusTooltip;"/>
|
||||
<label class="buffer-status-message-full"
|
||||
@ -188,6 +200,10 @@
|
||||
<label class="console-profile-command" />
|
||||
<label value="&profilerUI.console.stopCommandEnd;" />
|
||||
</hbox>
|
||||
<label class="realtime-disabled-message"
|
||||
value="Realtime recording data disabled on non-multiprocess Firefox."/>
|
||||
<label class="realtime-disabled-on-e10s-message"
|
||||
value="Enable multiprocess Firefox in preferences for rendering recording data in realtime."/>
|
||||
<label class="buffer-status-message"
|
||||
tooltiptext="&profilerUI.bufferStatusTooltip;"/>
|
||||
<label class="buffer-status-message-full"
|
||||
|
16
browser/devtools/performance/system.js
Normal file
16
browser/devtools/performance/system.js
Normal file
@ -0,0 +1,16 @@
|
||||
/* 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";
|
||||
|
||||
/**
|
||||
* A dump file to attach preprocessing directives consumable to the controller
|
||||
* without littering our code with directives.
|
||||
*/
|
||||
|
||||
const SYSTEM = {};
|
||||
|
||||
// If e10s is possible on the platform.
|
||||
#ifdef E10S_TESTING_ONLY
|
||||
SYSTEM.MULTIPROCESS_SUPPORTED = true;
|
||||
#endif
|
@ -11,8 +11,10 @@ support-files =
|
||||
# that need to be moved over to performance tool
|
||||
|
||||
[browser_perf-aaa-run-first-leaktest.js]
|
||||
[browser_marker-utils.js]
|
||||
[browser_markers-gc.js]
|
||||
[browser_markers-parse-html.js]
|
||||
[browser_markers-styles.js]
|
||||
[browser_markers-timestamp.js]
|
||||
[browser_perf-allocations-to-samples.js]
|
||||
[browser_perf-categories-js-calltree.js]
|
||||
@ -65,8 +67,10 @@ support-files =
|
||||
[browser_perf-jit-model-01.js]
|
||||
[browser_perf-jit-model-02.js]
|
||||
[browser_perf-loading-01.js]
|
||||
[browser_perf-loading-02.js]
|
||||
[browser_perf-options-01.js]
|
||||
[browser_perf-options-02.js]
|
||||
[browser_perf-options-03.js]
|
||||
[browser_perf-options-invert-call-tree-01.js]
|
||||
[browser_perf-options-invert-call-tree-02.js]
|
||||
[browser_perf-options-invert-flame-graph-01.js]
|
||||
@ -85,6 +89,7 @@ support-files =
|
||||
[browser_perf-overview-render-01.js]
|
||||
[browser_perf-overview-render-02.js]
|
||||
[browser_perf-overview-render-03.js]
|
||||
[browser_perf-overview-render-04.js]
|
||||
[browser_perf-overview-selection-01.js]
|
||||
[browser_perf-overview-selection-02.js]
|
||||
[browser_perf-overview-selection-03.js]
|
||||
@ -100,6 +105,7 @@ support-files =
|
||||
[browser_perf-recording-notices-02.js]
|
||||
[browser_perf-recording-notices-03.js]
|
||||
[browser_perf-recording-notices-04.js]
|
||||
[browser_perf-recording-notices-05.js]
|
||||
[browser_perf_recordings-io-01.js]
|
||||
[browser_perf_recordings-io-02.js]
|
||||
[browser_perf_recordings-io-03.js]
|
||||
|
37
browser/devtools/performance/test/browser_marker-utils.js
Normal file
37
browser/devtools/performance/test/browser_marker-utils.js
Normal file
@ -0,0 +1,37 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests the marker utils methods.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
let { TIMELINE_BLUEPRINT } = devtools.require("devtools/shared/timeline/global");
|
||||
let Utils = devtools.require("devtools/shared/timeline/marker-utils");
|
||||
|
||||
is(Utils.getMarkerLabel({ name: "DOMEvent" }), "DOM Event",
|
||||
"getMarkerLabel() returns a simple label");
|
||||
is(Utils.getMarkerLabel({ name: "Javascript", causeName: "js" }), "js",
|
||||
"getMarkerLabel() returns a label defined via function");
|
||||
|
||||
ok(Utils.getMarkerFields({ name: "Paint" }).length === 0,
|
||||
"getMarkerFields() returns an empty array when no fields defined");
|
||||
|
||||
let fields = Utils.getMarkerFields({ name: "ConsoleTime", causeName: "snowstorm" });
|
||||
is(fields[0].label, "Timer Name:", "getMarkerFields() returns an array with proper label");
|
||||
is(fields[0].value, "snowstorm", "getMarkerFields() returns an array with proper value");
|
||||
|
||||
fields = Utils.getMarkerFields({ name: "DOMEvent", type: "mouseclick" });
|
||||
is(fields.length, 1, "getMarkerFields() ignores fields that are not found on marker");
|
||||
is(fields[0].label, "Event Type:", "getMarkerFields() returns an array with proper label");
|
||||
is(fields[0].value, "mouseclick", "getMarkerFields() returns an array with proper value");
|
||||
|
||||
fields = Utils.getMarkerFields({ name: "DOMEvent", eventPhase: Ci.nsIDOMEvent.AT_TARGET, type: "mouseclick" });
|
||||
is(fields.length, 2, "getMarkerFields() returns multiple fields when they exist");
|
||||
is(fields[0].label, "Event Type:", "getMarkerFields() returns an array with proper label (ordered)");
|
||||
is(fields[0].value, "mouseclick", "getMarkerFields() returns an array with proper value (ordered)");
|
||||
is(fields[1].label, "Phase:", "getMarkerFields() returns an array with proper label (ordered)");
|
||||
is(fields[1].value, "Target", "getMarkerFields() uses the `formatter` function when available");
|
||||
|
||||
finish();
|
||||
}
|
38
browser/devtools/performance/test/browser_markers-styles.js
Normal file
38
browser/devtools/performance/test/browser_markers-styles.js
Normal file
@ -0,0 +1,38 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we get a "Styles" marker with the correct meta.
|
||||
*/
|
||||
|
||||
|
||||
function* spawnTest () {
|
||||
let { target, front } = yield initBackend(SIMPLE_URL);
|
||||
let markers = [];
|
||||
|
||||
front.on("timeline-data", handler);
|
||||
let model = yield front.startRecording({ withTicks: true });
|
||||
|
||||
yield waitUntil(() => {
|
||||
return markers.some(({restyleHint}) => restyleHint != void 0);
|
||||
});
|
||||
|
||||
front.off("timeline-data", handler);
|
||||
yield front.stopRecording(model);
|
||||
|
||||
info(`Got ${markers.length} markers.`);
|
||||
|
||||
ok(markers.every(({name}) => name === "Styles"), "All markers found are Styles markers");
|
||||
ok(markers.length, "found some restyle markers");
|
||||
|
||||
ok(markers.some(({restyleHint}) => restyleHint != void 0), "some markers have a restyleHint property");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
|
||||
function handler (_, name, m) {
|
||||
if (name === "markers") {
|
||||
markers = markers.concat(m.filter(marker => marker.name === "Styles"));
|
||||
}
|
||||
}
|
||||
}
|
78
browser/devtools/performance/test/browser_perf-loading-02.js
Normal file
78
browser/devtools/performance/test/browser_perf-loading-02.js
Normal file
@ -0,0 +1,78 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that the details view is locked after recording has stopped and before
|
||||
* the recording has finished loading.
|
||||
* Also test that the details view isn't locked if the recording that is being
|
||||
* stopped isn't the active one.
|
||||
*/
|
||||
|
||||
let test = Task.async(function*() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { PerformanceController, PerformanceView, RecordingsView,
|
||||
EVENTS, $ } = panel.panelWin;
|
||||
|
||||
let detailsContainer = $("#details-pane-container");
|
||||
let recordingNotice = $("#recording-notice");
|
||||
let loadingNotice = $("#loading-notice");
|
||||
let detailsPane = $("#details-pane");
|
||||
|
||||
info("Start to record");
|
||||
yield startRecording(panel);
|
||||
|
||||
is(detailsContainer.selectedPanel, recordingNotice,
|
||||
"The recording-notice is shown while recording");
|
||||
|
||||
info("Stop the recording and wait for the WILL_STOP and STOPPED events");
|
||||
let clicked = PerformanceView.once(EVENTS.UI_STOP_RECORDING);
|
||||
let willStop = PerformanceController.once(EVENTS.RECORDING_WILL_STOP);
|
||||
let hasStopped = PerformanceController.once(EVENTS.RECORDING_STOPPED);
|
||||
|
||||
click(panel.panelWin, $("#main-record-button"));
|
||||
yield clicked;
|
||||
yield willStop;
|
||||
|
||||
is(detailsContainer.selectedPanel, loadingNotice,
|
||||
"The loading-notice is shown while the record is stopping");
|
||||
|
||||
let stateChanged = once(PerformanceView, EVENTS.UI_STATE_CHANGED);
|
||||
yield hasStopped;
|
||||
yield stateChanged;
|
||||
|
||||
is(detailsContainer.selectedPanel, detailsPane,
|
||||
"The details panel is shown after the record has stopped");
|
||||
|
||||
info("Start to record again");
|
||||
yield startRecording(panel);
|
||||
|
||||
info("While the 2nd record is still going, switch to the first one");
|
||||
let select = once(PerformanceController, EVENTS.RECORDING_SELECTED);
|
||||
RecordingsView.selectedIndex = 0;
|
||||
yield select;
|
||||
|
||||
info("Stop the 2nd recording and wait for the WILL_STOP and STOPPED events");
|
||||
clicked = PerformanceView.once(EVENTS.UI_STOP_RECORDING);
|
||||
willStop = PerformanceController.once(EVENTS.RECORDING_WILL_STOP);
|
||||
hasStopped = PerformanceController.once(EVENTS.RECORDING_STOPPED);
|
||||
|
||||
click(panel.panelWin, $("#main-record-button"));
|
||||
yield clicked;
|
||||
yield willStop;
|
||||
|
||||
is(detailsContainer.selectedPanel, detailsPane,
|
||||
"The details panel is still shown while the 2nd record is being stopped");
|
||||
is(RecordingsView.selectedIndex, 0, "The first record is still selected");
|
||||
|
||||
stateChanged = once(PerformanceView, EVENTS.UI_STATE_CHANGED);
|
||||
yield hasStopped;
|
||||
yield stateChanged;
|
||||
|
||||
is(detailsContainer.selectedPanel, detailsPane,
|
||||
"The details panel is still shown after the 2nd record has stopped");
|
||||
is(RecordingsView.selectedIndex, 1, "The second record is now selected");
|
||||
|
||||
yield PerformanceController.clearRecordings();
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
});
|
27
browser/devtools/performance/test/browser_perf-options-03.js
Normal file
27
browser/devtools/performance/test/browser_perf-options-03.js
Normal file
@ -0,0 +1,27 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that toggling meta option prefs change visibility of other options.
|
||||
*/
|
||||
|
||||
Services.prefs.setBoolPref(EXPERIMENTAL_PREF, false);
|
||||
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, EVENTS, PerformanceController } = panel.panelWin;
|
||||
|
||||
let $body = $(".theme-body");
|
||||
let $menu = $("#performance-options-menupopup");
|
||||
|
||||
ok(!$body.classList.contains("experimental-enabled"), "body does not have `experimental-enabled` on start");
|
||||
ok(!$menu.classList.contains("experimental-enabled"), "menu does not have `experimental-enabled` on start");
|
||||
|
||||
Services.prefs.setBoolPref(EXPERIMENTAL_PREF, true);
|
||||
|
||||
ok($body.classList.contains("experimental-enabled"), "body has `experimental-enabled` after toggle");
|
||||
ok($menu.classList.contains("experimental-enabled"), "menu has `experimental-enabled` after toggle");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that the overview graphs do not render when realtime rendering is off
|
||||
* due to lack of e10s.
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, EVENTS, PerformanceController, OverviewView, RecordingsView } = panel.panelWin;
|
||||
|
||||
let updated = 0;
|
||||
OverviewView.on(EVENTS.OVERVIEW_RENDERED, () => updated++);
|
||||
OverviewView.OVERVIEW_UPDATE_INTERVAL = 1;
|
||||
|
||||
// Set realtime rendering off.
|
||||
OverviewView.isRealtimeRenderingEnabled = () => false;
|
||||
|
||||
yield startRecording(panel, { waitForOverview: false, waitForStateChange: true });
|
||||
is($("#overview-pane").hidden, true, "overview graphs hidden");
|
||||
is(updated, 0, "Overview graphs have still not been updated");
|
||||
yield waitUntil(() => PerformanceController.getCurrentRecording().getMarkers().length);
|
||||
yield waitUntil(() => PerformanceController.getCurrentRecording().getTicks().length);
|
||||
is(updated, 0, "Overview graphs have still not been updated");
|
||||
|
||||
yield stopRecording(panel);
|
||||
|
||||
let markers = OverviewView.graphs.get("timeline");
|
||||
let framerate = OverviewView.graphs.get("framerate");
|
||||
|
||||
ok(markers.width > 0,
|
||||
"The overview's markers graph has a width.");
|
||||
ok(framerate.width > 0,
|
||||
"The overview's framerate graph has a width.");
|
||||
|
||||
is(updated, 1, "Overview graphs rendered upon completion.");
|
||||
is($("#overview-pane").hidden, false, "overview graphs no longer hidden");
|
||||
|
||||
yield startRecording(panel, { waitForOverview: false, waitForStateChange: true });
|
||||
is($("#overview-pane").hidden, true, "overview graphs hidden again when starting new recording");
|
||||
|
||||
RecordingsView.selectedIndex = 0;
|
||||
is($("#overview-pane").hidden, false, "overview graphs no longer hidden when switching back to complete recording.");
|
||||
RecordingsView.selectedIndex = 1;
|
||||
is($("#overview-pane").hidden, true, "overview graphs hidden again when going back to inprogress recording.");
|
||||
|
||||
yield stopRecording(panel);
|
||||
is($("#overview-pane").hidden, false, "overview graphs no longer hidden when recording finishes");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that when a recording overlaps the circular buffer, that
|
||||
* a class is assigned to the recording notices.
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL, void 0, { TEST_MOCK_PROFILER_CHECK_TIMER: 10 });
|
||||
let { EVENTS, $, PerformanceController, PerformanceView } = panel.panelWin;
|
||||
|
||||
let supported = false;
|
||||
let enabled = false;
|
||||
|
||||
PerformanceController.getMultiprocessStatus = () => {
|
||||
return { supported, enabled };
|
||||
};
|
||||
|
||||
PerformanceController._setMultiprocessAttributes();
|
||||
ok($("#performance-view").getAttribute("e10s"), "unsupported",
|
||||
"when e10s is disabled and no option to turn on, container has [e10s=unsupported]");
|
||||
|
||||
supported = true;
|
||||
enabled = false;
|
||||
PerformanceController._setMultiprocessAttributes();
|
||||
ok($("#performance-view").getAttribute("e10s"), "disabled",
|
||||
"when e10s is disabled and but is supported, container has [e10s=disabled]");
|
||||
|
||||
supported = false;
|
||||
enabled = true;
|
||||
PerformanceController._setMultiprocessAttributes();
|
||||
ok($("#performance-view").getAttribute("e10s"), "",
|
||||
"when e10s is enabled, but not supported, this probably means we no longer have E10S_TESTING_ONLY, and we have no e10s attribute.");
|
||||
|
||||
supported = true;
|
||||
enabled = true;
|
||||
PerformanceController._setMultiprocessAttributes();
|
||||
ok($("#performance-view").getAttribute("e10s"), "",
|
||||
"when e10s is enabled and supported, there should be no e10s attribute.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
@ -9,6 +9,7 @@ function spawnTest () {
|
||||
let { target, panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, $$, EVENTS, PerformanceController, OverviewView } = panel.panelWin;
|
||||
let { L10N, TIMELINE_BLUEPRINT } = devtools.require("devtools/shared/timeline/global");
|
||||
let { getMarkerLabel } = devtools.require("devtools/shared/timeline/marker-utils");
|
||||
|
||||
yield startRecording(panel);
|
||||
ok(true, "Recording has started.");
|
||||
@ -38,20 +39,14 @@ function spawnTest () {
|
||||
bar.click();
|
||||
let m = markers[i];
|
||||
|
||||
let name = TIMELINE_BLUEPRINT[m.name].label;
|
||||
|
||||
is($("#waterfall-details .marker-details-type").getAttribute("value"), name,
|
||||
is($("#waterfall-details .marker-details-type").getAttribute("value"), getMarkerLabel(m),
|
||||
"sidebar title matches markers name");
|
||||
|
||||
let printedStartTime = $(".marker-details-start .marker-details-labelvalue").getAttribute("value");
|
||||
let printedEndTime = $(".marker-details-end .marker-details-labelvalue").getAttribute("value");
|
||||
let printedDuration= $(".marker-details-duration .marker-details-labelvalue").getAttribute("value");
|
||||
let printedDuration = $(".marker-details-duration .marker-details-labelvalue").getAttribute("value");
|
||||
|
||||
let toMs = ms => L10N.getFormatStrWithNumbers("timeline.tick", ms);
|
||||
|
||||
// Values are rounded. We don't use a strict equality.
|
||||
is(toMs(m.start), printedStartTime, "sidebar start time is valid");
|
||||
is(toMs(m.end), printedEndTime, "sidebar end time is valid");
|
||||
is(toMs(m.end - m.start), printedDuration, "sidebar duration is valid");
|
||||
}
|
||||
yield teardown(panel);
|
||||
|
@ -37,6 +37,7 @@ const INVERT_PREF = "devtools.performance.ui.invert-call-tree";
|
||||
const INVERT_FLAME_PREF = "devtools.performance.ui.invert-flame-graph";
|
||||
const FLATTEN_PREF = "devtools.performance.ui.flatten-tree-recursion";
|
||||
const JIT_PREF = "devtools.performance.ui.show-jit-optimizations";
|
||||
const EXPERIMENTAL_PREF = "devtools.performance.ui.experimental";
|
||||
|
||||
// All tests are asynchronous.
|
||||
waitForExplicitFinish();
|
||||
@ -56,6 +57,7 @@ let DEFAULT_PREFS = [
|
||||
"devtools.performance.memory.max-log-length",
|
||||
"devtools.performance.profiler.buffer-size",
|
||||
"devtools.performance.profiler.sample-frequency-khz",
|
||||
"devtools.performance.ui.experimental",
|
||||
].reduce((prefs, pref) => {
|
||||
prefs[pref] = Preferences.get(pref);
|
||||
return prefs;
|
||||
|
@ -30,6 +30,12 @@ const GRAPH_REQUIREMENTS = {
|
||||
*/
|
||||
let OverviewView = {
|
||||
|
||||
/**
|
||||
* How frequently we attempt to render the graphs. Overridden
|
||||
* in tests.
|
||||
*/
|
||||
OVERVIEW_UPDATE_INTERVAL: OVERVIEW_UPDATE_INTERVAL,
|
||||
|
||||
/**
|
||||
* Sets up the view with event binding.
|
||||
*/
|
||||
@ -46,6 +52,9 @@ let OverviewView = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Store info on multiprocess support.
|
||||
this._multiprocessData = PerformanceController.getMultiprocessStatus();
|
||||
|
||||
this._onRecordingWillStart = this._onRecordingWillStart.bind(this);
|
||||
this._onRecordingStarted = this._onRecordingStarted.bind(this);
|
||||
this._onRecordingWillStop = this._onRecordingWillStop.bind(this);
|
||||
@ -173,6 +182,7 @@ let OverviewView = {
|
||||
if (this.isDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let recording = PerformanceController.getCurrentRecording();
|
||||
yield this.graphs.render(recording.getAllData(), resolution);
|
||||
|
||||
@ -197,7 +207,7 @@ let OverviewView = {
|
||||
// Check here to see if there's still a _timeoutId, incase
|
||||
// `stop` was called before the _prepareNextTick call was executed.
|
||||
if (this.isRendering()) {
|
||||
this._timeoutId = setTimeout(this._onRecordingTick, OVERVIEW_UPDATE_INTERVAL);
|
||||
this._timeoutId = setTimeout(this._onRecordingTick, this.OVERVIEW_UPDATE_INTERVAL);
|
||||
}
|
||||
},
|
||||
|
||||
@ -255,7 +265,7 @@ let OverviewView = {
|
||||
* Start the polling for rendering the overview graph.
|
||||
*/
|
||||
_startPolling: function () {
|
||||
this._timeoutId = setTimeout(this._onRecordingTick, OVERVIEW_UPDATE_INTERVAL);
|
||||
this._timeoutId = setTimeout(this._onRecordingTick, this.OVERVIEW_UPDATE_INTERVAL);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -340,6 +350,35 @@ let OverviewView = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch the multiprocess status and if e10s is not currently on, disable
|
||||
* realtime rendering.
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
isRealtimeRenderingEnabled: function () {
|
||||
return this._multiprocessData.enabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* Show the graphs overview panel when a recording is finished
|
||||
* when non-realtime graphs are enabled. Also set the graph visibility
|
||||
* so the performance graphs know which graphs to render.
|
||||
*
|
||||
* @param {RecordingModel} recording
|
||||
*/
|
||||
_showGraphsPanel: function (recording) {
|
||||
this._setGraphVisibilityFromRecordingFeatures(recording);
|
||||
$("#overview-pane").hidden = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the graphs container completely.
|
||||
*/
|
||||
_hideGraphsPanel: function () {
|
||||
$("#overview-pane").hidden = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when `devtools.theme` changes.
|
||||
*/
|
||||
@ -361,14 +400,28 @@ let OverviewView = {
|
||||
* @return {function}
|
||||
*/
|
||||
function OverviewViewOnStateChange (fn) {
|
||||
return function _onRecordingStateChange () {
|
||||
return function _onRecordingStateChange (eventName, recording) {
|
||||
let currentRecording = PerformanceController.getCurrentRecording();
|
||||
|
||||
// All these methods require a recording to exist.
|
||||
if (!currentRecording) {
|
||||
// All these methods require a recording to exist selected and
|
||||
// from the event name, since there is a delay between starting
|
||||
// a recording and changing the selection.
|
||||
if (!currentRecording || !recording) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If realtime rendering is not enabed (e10s not on), then
|
||||
// show the disabled message, or the full graphs if the recording is completed
|
||||
if (!this.isRealtimeRenderingEnabled()) {
|
||||
if (recording.isRecording()) {
|
||||
this._hideGraphsPanel();
|
||||
// Abort, as we do not want to change polling status.
|
||||
return;
|
||||
} else {
|
||||
this._showGraphsPanel(recording);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isRendering() && !currentRecording.isRecording()) {
|
||||
this._stopPolling();
|
||||
} else if (currentRecording.isRecording() && !this.isRendering()) {
|
||||
|
@ -214,7 +214,8 @@ let RecordingsView = Heritage.extend(WidgetMethods, {
|
||||
*/
|
||||
_onSaveButtonClick: function (e) {
|
||||
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
||||
fp.init(window, L10N.getStr("recordingsList.saveDialogTitle"), Ci.nsIFilePicker.modeSave);
|
||||
// TODO localize? in bug 1163763
|
||||
fp.init(window, "Save recording…", Ci.nsIFilePicker.modeSave);
|
||||
fp.appendFilter(L10N.getStr("recordingsList.saveDialogJSONFilter"), "*.json");
|
||||
fp.appendFilter(L10N.getStr("recordingsList.saveDialogAllFilter"), "*.*");
|
||||
fp.defaultString = "profile.json";
|
||||
|
@ -15,12 +15,18 @@ let ToolbarView = {
|
||||
this._onFilterPopupHiding = this._onFilterPopupHiding.bind(this);
|
||||
this._onHiddenMarkersChanged = this._onHiddenMarkersChanged.bind(this);
|
||||
this._onPrefChanged = this._onPrefChanged.bind(this);
|
||||
this._popup = $("#performance-options-menupopup");
|
||||
|
||||
this.optionsView = new OptionsView({
|
||||
branchName: BRANCH_NAME,
|
||||
menupopup: $("#performance-options-menupopup")
|
||||
menupopup: this._popup
|
||||
});
|
||||
|
||||
// Set the visibility of experimental UI options on load
|
||||
// based off of `devtools.performance.ui.experimental` preference
|
||||
let experimentalEnabled = PerformanceController.getOption("experimental");
|
||||
this._toggleExperimentalUI(experimentalEnabled);
|
||||
|
||||
yield this.optionsView.initialize();
|
||||
this.optionsView.on("pref-changed", this._onPrefChanged);
|
||||
|
||||
@ -36,6 +42,7 @@ let ToolbarView = {
|
||||
destroy: function () {
|
||||
$("#performance-filter-menupopup").removeEventListener("popupshowing", this._onFilterPopupShowing);
|
||||
$("#performance-filter-menupopup").removeEventListener("popuphiding", this._onFilterPopupHiding);
|
||||
this._popup = null
|
||||
|
||||
this.optionsView.off("pref-changed", this._onPrefChanged);
|
||||
this.optionsView.destroy();
|
||||
@ -77,6 +84,29 @@ let ToolbarView = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fired when `devtools.performance.ui.experimental` is changed, or
|
||||
* during init. Toggles the visibility of experimental performance tool options
|
||||
* in the UI options.
|
||||
*
|
||||
* Sets or removes "experimental-enabled" on the menu and main elements,
|
||||
* hiding or showing all elements with class "experimental-option".
|
||||
*
|
||||
* TODO re-enable "#option-enable-memory" permanently once stable in bug 1163350
|
||||
* TODO re-enable "#option-show-jit-optimizations" permanently once stable in bug 1163351
|
||||
*
|
||||
* @param {boolean} isEnabled
|
||||
*/
|
||||
_toggleExperimentalUI: function (isEnabled) {
|
||||
if (isEnabled) {
|
||||
$(".theme-body").classList.add("experimental-enabled");
|
||||
this._popup.classList.add("experimental-enabled");
|
||||
} else {
|
||||
$(".theme-body").classList.remove("experimental-enabled");
|
||||
this._popup.classList.remove("experimental-enabled");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fired when the markers filter popup starts to show.
|
||||
*/
|
||||
@ -105,7 +135,12 @@ let ToolbarView = {
|
||||
* Propogated by the PerformanceController.
|
||||
*/
|
||||
_onPrefChanged: function (_, prefName) {
|
||||
let value = Services.prefs.getBoolPref(BRANCH_NAME + prefName);
|
||||
let value = PerformanceController.getOption(prefName);
|
||||
|
||||
if (prefName === "experimental") {
|
||||
this._toggleExperimentalUI(value);
|
||||
}
|
||||
|
||||
this.emit(EVENTS.PREF_CHANGED, prefName, value);
|
||||
},
|
||||
|
||||
|
@ -41,6 +41,7 @@ EXTRA_JS_MODULES.devtools.shared.profiler += [
|
||||
EXTRA_JS_MODULES.devtools.shared.timeline += [
|
||||
'timeline/global.js',
|
||||
'timeline/marker-details.js',
|
||||
'timeline/marker-utils.js',
|
||||
'timeline/markers-overview.js',
|
||||
'timeline/waterfall.js',
|
||||
]
|
||||
|
@ -16,19 +16,35 @@ const L10N = new ViewHelpers.L10N(STRINGS_URI);
|
||||
/**
|
||||
* A simple schema for mapping markers to the timeline UI. The keys correspond
|
||||
* to marker names, while the values are objects with the following format:
|
||||
*
|
||||
* - group: the row index in the timeline overview graph; multiple markers
|
||||
* can be added on the same row. @see <overview.js/buildGraphImage>
|
||||
* - label: the label used in the waterfall to identify the marker
|
||||
* - colorName: the name of the DevTools color used for this marker. If adding
|
||||
* - label: the label used in the waterfall to identify the marker. Can be a
|
||||
* string or just a function that accepts the marker and returns a string,
|
||||
* if you want to use a dynamic property for the main label.
|
||||
* - colorName: the label of the DevTools color used for this marker. If adding
|
||||
* a new color, be sure to check that there's an entry for
|
||||
* `.marker-details-bullet.{COLORNAME}` for the equivilent entry
|
||||
* in ./browser/themes/shared/devtools/performance.inc.css
|
||||
* https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors
|
||||
* - fields: An optional array of marker properties you wish to display in the
|
||||
* marker details view. For example, a field of
|
||||
* { property: "aCauseName", label: "Cause" }
|
||||
* would render a field like `Cause: ${marker.aCauseName}`.
|
||||
* Each `field` item may take the following properties:
|
||||
*
|
||||
* - property: The property that must exist on the marker to render, and
|
||||
* the value of the property will be displayed.
|
||||
* - label: The name of the property that should be displayed.
|
||||
* - formatter: If a formatter is provided, instead of directly using the `property`
|
||||
* property on the marker, the marker is passed into the formatter
|
||||
* function to determine the display value.
|
||||
*
|
||||
* Whenever this is changed, browser_timeline_waterfall-styles.js *must* be
|
||||
* updated as well.
|
||||
*/
|
||||
const TIMELINE_BLUEPRINT = {
|
||||
/* Group 0 - Reflow and Rendering pipeline */
|
||||
"Styles": {
|
||||
group: 0,
|
||||
colorName: "highlight-pink",
|
||||
@ -44,15 +60,25 @@ const TIMELINE_BLUEPRINT = {
|
||||
colorName: "highlight-green",
|
||||
label: L10N.getStr("timeline.label.paint")
|
||||
},
|
||||
|
||||
/* Group 1 - JS */
|
||||
"DOMEvent": {
|
||||
group: 1,
|
||||
colorName: "highlight-lightorange",
|
||||
label: L10N.getStr("timeline.label.domevent")
|
||||
label: L10N.getStr("timeline.label.domevent"),
|
||||
fields: [{
|
||||
property: "type",
|
||||
label: L10N.getStr("timeline.markerDetail.DOMEventType")
|
||||
}, {
|
||||
property: "eventPhase",
|
||||
label: L10N.getStr("timeline.markerDetail.DOMEventPhase"),
|
||||
formatter: getEventPhaseName
|
||||
}]
|
||||
},
|
||||
"Javascript": {
|
||||
group: 1,
|
||||
colorName: "highlight-lightorange",
|
||||
label: L10N.getStr("timeline.label.javascript2")
|
||||
label: (marker) => marker.causeName,
|
||||
},
|
||||
"Parse HTML": {
|
||||
group: 1,
|
||||
@ -67,12 +93,22 @@ const TIMELINE_BLUEPRINT = {
|
||||
"GarbageCollection": {
|
||||
group: 1,
|
||||
colorName: "highlight-red",
|
||||
label: L10N.getStr("timeline.label.garbageCollection")
|
||||
label: getGCLabel,
|
||||
fields: [
|
||||
{ property: "causeName", label: "Reason:" },
|
||||
{ property: "nonincrementalReason", label: "Non-incremental Reason:" }
|
||||
]
|
||||
},
|
||||
|
||||
/* Group 2 - User Controlled */
|
||||
"ConsoleTime": {
|
||||
group: 2,
|
||||
colorName: "highlight-bluegrey",
|
||||
label: L10N.getStr("timeline.label.consoleTime")
|
||||
label: L10N.getStr("timeline.label.consoleTime"),
|
||||
fields: [{
|
||||
property: "causeName",
|
||||
label: L10N.getStr("timeline.markerDetail.consoleTimerName")
|
||||
}]
|
||||
},
|
||||
"TimeStamp": {
|
||||
group: 2,
|
||||
@ -81,6 +117,30 @@ const TIMELINE_BLUEPRINT = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* A series of formatters used by the blueprint.
|
||||
*/
|
||||
|
||||
function getEventPhaseName (marker) {
|
||||
if (marker.eventPhase === Ci.nsIDOMEvent.AT_TARGET) {
|
||||
return L10N.getStr("timeline.markerDetail.DOMEventTargetPhase");
|
||||
} else if (marker.eventPhase === Ci.nsIDOMEvent.CAPTURING_PHASE) {
|
||||
return L10N.getStr("timeline.markerDetail.DOMEventCapturingPhase");
|
||||
} else if (marker.eventPhase === Ci.nsIDOMEvent.BUBBLING_PHASE) {
|
||||
return L10N.getStr("timeline.markerDetail.DOMEventBubblingPhase");
|
||||
}
|
||||
}
|
||||
|
||||
function getGCLabel (marker) {
|
||||
let label = L10N.getStr("timeline.label.garbageCollection");
|
||||
// Only if a `nonincrementalReason` exists, do we want to label
|
||||
// this as a non incremental GC event.
|
||||
if ("nonincrementalReason" in marker) {
|
||||
label = `${label} (Non-incremental)`;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
// Exported symbols.
|
||||
exports.L10N = L10N;
|
||||
exports.TIMELINE_BLUEPRINT = TIMELINE_BLUEPRINT;
|
||||
|
@ -16,6 +16,8 @@ loader.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
|
||||
"devtools/shared/timeline/global", true);
|
||||
loader.lazyRequireGetter(this, "EventEmitter",
|
||||
"devtools/toolkit/event-emitter");
|
||||
loader.lazyRequireGetter(this, "MarkerUtils",
|
||||
"devtools/shared/timeline/marker-utils");
|
||||
|
||||
/**
|
||||
* A detailed view for one single marker.
|
||||
@ -50,54 +52,6 @@ MarkerDetails.prototype = {
|
||||
this._parent.innerHTML = "";
|
||||
},
|
||||
|
||||
/**
|
||||
* Builds the label representing marker's type.
|
||||
*
|
||||
* @param string type
|
||||
* Could be "Paint", "Reflow", "Styles", ...
|
||||
* See TIMELINE_BLUEPRINT in widgets/global.js
|
||||
*/
|
||||
buildMarkerTypeLabel: function(type) {
|
||||
let blueprint = TIMELINE_BLUEPRINT[type];
|
||||
|
||||
let hbox = this._document.createElement("hbox");
|
||||
hbox.setAttribute("align", "center");
|
||||
|
||||
let bullet = this._document.createElement("hbox");
|
||||
bullet.className = `marker-details-bullet ${blueprint.colorName}`;
|
||||
|
||||
let label = this._document.createElement("label");
|
||||
label.className = "marker-details-type";
|
||||
label.setAttribute("value", blueprint.label);
|
||||
|
||||
hbox.appendChild(bullet);
|
||||
hbox.appendChild(label);
|
||||
|
||||
return hbox;
|
||||
},
|
||||
|
||||
/**
|
||||
* Builds labels for name:value pairs. Like "Start: 100ms",
|
||||
* "Duration: 200ms", ...
|
||||
*
|
||||
* @param string l10nName
|
||||
* String identifier for label's name.
|
||||
* @param string value
|
||||
* Label's value.
|
||||
*/
|
||||
buildNameValueLabel: function(l10nName, value) {
|
||||
let hbox = this._document.createElement("hbox");
|
||||
let labelName = this._document.createElement("label");
|
||||
let labelValue = this._document.createElement("label");
|
||||
labelName.className = "plain marker-details-labelname";
|
||||
labelValue.className = "plain marker-details-labelvalue";
|
||||
labelName.setAttribute("value", L10N.getStr(l10nName));
|
||||
labelValue.setAttribute("value", value);
|
||||
hbox.appendChild(labelName);
|
||||
hbox.appendChild(labelValue);
|
||||
return hbox;
|
||||
},
|
||||
|
||||
/**
|
||||
* Populates view with marker's details.
|
||||
*
|
||||
@ -112,37 +66,13 @@ MarkerDetails.prototype = {
|
||||
|
||||
// UI for any marker
|
||||
|
||||
let title = this.buildMarkerTypeLabel(marker.name);
|
||||
|
||||
let toMs = ms => L10N.getFormatStrWithNumbers("timeline.tick", ms);
|
||||
|
||||
let start = this.buildNameValueLabel("timeline.markerDetail.start", toMs(marker.start));
|
||||
let end = this.buildNameValueLabel("timeline.markerDetail.end", toMs(marker.end));
|
||||
let duration = this.buildNameValueLabel("timeline.markerDetail.duration", toMs(marker.end - marker.start));
|
||||
|
||||
start.classList.add("marker-details-start");
|
||||
end.classList.add("marker-details-end");
|
||||
duration.classList.add("marker-details-duration");
|
||||
let title = MarkerUtils.DOM.buildTitle(this._document, marker);
|
||||
let duration = MarkerUtils.DOM.buildDuration(this._document, marker);
|
||||
let fields = MarkerUtils.DOM.buildFields(this._document, marker);
|
||||
|
||||
this._parent.appendChild(title);
|
||||
this._parent.appendChild(start);
|
||||
this._parent.appendChild(end);
|
||||
this._parent.appendChild(duration);
|
||||
|
||||
// UI for specific markers
|
||||
|
||||
switch (marker.name) {
|
||||
case "ConsoleTime":
|
||||
this.renderConsoleTimeMarker(this._parent, marker);
|
||||
break;
|
||||
case "DOMEvent":
|
||||
this.renderDOMEventMarker(this._parent, marker);
|
||||
break;
|
||||
case "Javascript":
|
||||
this.renderJavascriptMarker(this._parent, marker);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
fields.forEach(field => this._parent.appendChild(field));
|
||||
|
||||
if (marker.stack) {
|
||||
let property = "timeline.markerDetail.stack";
|
||||
@ -242,66 +172,6 @@ MarkerDetails.prototype = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Render details of a console marker (console.time).
|
||||
*
|
||||
* @param nsIDOMNode parent
|
||||
* The parent node holding the view.
|
||||
* @param object marker
|
||||
* The marker to display.
|
||||
*/
|
||||
renderConsoleTimeMarker: function(parent, marker) {
|
||||
if ("causeName" in marker) {
|
||||
let timerName = this.buildNameValueLabel("timeline.markerDetail.consoleTimerName", marker.causeName);
|
||||
this._parent.appendChild(timerName);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Render details of a DOM Event marker.
|
||||
*
|
||||
* @param nsIDOMNode parent
|
||||
* The parent node holding the view.
|
||||
* @param object marker
|
||||
* The marker to display.
|
||||
*/
|
||||
renderDOMEventMarker: function(parent, marker) {
|
||||
if ("type" in marker) {
|
||||
let type = this.buildNameValueLabel("timeline.markerDetail.DOMEventType", marker.type);
|
||||
this._parent.appendChild(type);
|
||||
}
|
||||
if ("eventPhase" in marker) {
|
||||
let phaseL10NProp;
|
||||
if (marker.eventPhase == Ci.nsIDOMEvent.AT_TARGET) {
|
||||
phaseL10NProp = "timeline.markerDetail.DOMEventTargetPhase";
|
||||
}
|
||||
if (marker.eventPhase == Ci.nsIDOMEvent.CAPTURING_PHASE) {
|
||||
phaseL10NProp = "timeline.markerDetail.DOMEventCapturingPhase";
|
||||
}
|
||||
if (marker.eventPhase == Ci.nsIDOMEvent.BUBBLING_PHASE) {
|
||||
phaseL10NProp = "timeline.markerDetail.DOMEventBubblingPhase";
|
||||
}
|
||||
let phase = this.buildNameValueLabel("timeline.markerDetail.DOMEventPhase", L10N.getStr(phaseL10NProp));
|
||||
this._parent.appendChild(phase);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Render details of a Javascript marker.
|
||||
*
|
||||
* @param nsIDOMNode parent
|
||||
* The parent node holding the view.
|
||||
* @param object marker
|
||||
* The marker to display.
|
||||
*/
|
||||
renderJavascriptMarker: function(parent, marker) {
|
||||
if ("causeName" in marker) {
|
||||
let cause = this.buildNameValueLabel("timeline.markerDetail.causeName", marker.causeName);
|
||||
this._parent.appendChild(cause);
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
exports.MarkerDetails = MarkerDetails;
|
||||
|
141
browser/devtools/shared/timeline/marker-utils.js
Normal file
141
browser/devtools/shared/timeline/marker-utils.js
Normal file
@ -0,0 +1,141 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
loader.lazyRequireGetter(this, "L10N",
|
||||
"devtools/shared/timeline/global", true);
|
||||
loader.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
|
||||
"devtools/shared/timeline/global", true);
|
||||
|
||||
/**
|
||||
* Returns the correct label to display for passed in marker, based
|
||||
* off of the blueprints.
|
||||
*
|
||||
* @param {ProfileTimelineMarker} marker
|
||||
* @return {string}
|
||||
*/
|
||||
function getMarkerLabel (marker) {
|
||||
let blueprint = TIMELINE_BLUEPRINT[marker.name];
|
||||
// Either use the label function in the blueprint, or use it directly
|
||||
// as a string.
|
||||
return typeof blueprint.label === "function" ? blueprint.label(marker) : blueprint.label;
|
||||
}
|
||||
exports.getMarkerLabel = getMarkerLabel;
|
||||
|
||||
/**
|
||||
* Returns an array of objects with key/value pairs of what should be rendered
|
||||
* in the marker details view.
|
||||
*
|
||||
* @param {ProfileTimelineMarker} marker
|
||||
* @return {Array<object>}
|
||||
*/
|
||||
function getMarkerFields (marker) {
|
||||
let blueprint = TIMELINE_BLUEPRINT[marker.name];
|
||||
return (blueprint.fields || []).reduce((fields, field) => {
|
||||
// Ensure this marker has this field present
|
||||
if (field.property in marker) {
|
||||
let label = field.label;
|
||||
let value = marker[field.property];
|
||||
// If a formatter function defined, use it to get the
|
||||
// value we actually want to display.
|
||||
if (typeof field.formatter === "function") {
|
||||
value = field.formatter(marker);
|
||||
}
|
||||
fields.push({ label, value });
|
||||
}
|
||||
return fields;
|
||||
}, []);
|
||||
}
|
||||
exports.getMarkerFields = getMarkerFields;
|
||||
|
||||
/**
|
||||
* Utilites for creating elements for markers.
|
||||
*/
|
||||
const DOM = exports.DOM = {
|
||||
/**
|
||||
* Builds all the fields possible for the given marker. Returns an
|
||||
* array of elements to be appended to a parent element.
|
||||
*
|
||||
* @param {Document} doc
|
||||
* @param {ProfileTimelineMarker} marker
|
||||
* @return {Array<Element>}
|
||||
*/
|
||||
buildFields: function (doc, marker) {
|
||||
let blueprint = TIMELINE_BLUEPRINT[marker.name];
|
||||
let fields = getMarkerFields(marker);
|
||||
|
||||
return fields.map(({ label, value }) => DOM.buildNameValueLabel(doc, label, value));
|
||||
},
|
||||
|
||||
/**
|
||||
* Builds the label representing marker's type.
|
||||
*
|
||||
* @param {Document} doc
|
||||
* @param {ProfileTimelineMarker}
|
||||
* @return {Element}
|
||||
*/
|
||||
buildTitle: function (doc, marker) {
|
||||
let blueprint = TIMELINE_BLUEPRINT[marker.name];
|
||||
|
||||
let hbox = doc.createElement("hbox");
|
||||
hbox.setAttribute("align", "center");
|
||||
|
||||
let bullet = doc.createElement("hbox");
|
||||
bullet.className = `marker-details-bullet ${blueprint.colorName}`;
|
||||
|
||||
let title = getMarkerLabel(marker);
|
||||
let label = doc.createElement("label");
|
||||
label.className = "marker-details-type";
|
||||
label.setAttribute("value", title);
|
||||
|
||||
hbox.appendChild(bullet);
|
||||
hbox.appendChild(label);
|
||||
|
||||
return hbox;
|
||||
},
|
||||
|
||||
/**
|
||||
* Builds the duration element, like "Duration: 200ms".
|
||||
*
|
||||
* @param {Document} doc
|
||||
* @param {ProfileTimelineMarker} marker
|
||||
* @return {Element}
|
||||
*/
|
||||
buildDuration: function (doc, marker) {
|
||||
let label = L10N.getStr("timeline.markerDetail.duration");
|
||||
let value = L10N.getFormatStrWithNumbers("timeline.tick", marker.end - marker.start);
|
||||
let el = DOM.buildNameValueLabel(doc, label, value);
|
||||
el.classList.add("marker-details-duration");
|
||||
return el;
|
||||
},
|
||||
|
||||
/**
|
||||
* Builds labels for name:value pairs. Like "Start: 100ms",
|
||||
* "Duration: 200ms", ...
|
||||
*
|
||||
* @param {Document} doc
|
||||
* @param string field
|
||||
* String identifier for label's name.
|
||||
* @param string value
|
||||
* Label's value.
|
||||
* @return {Element}
|
||||
*/
|
||||
buildNameValueLabel: function (doc, field, value) {
|
||||
let hbox = doc.createElement("hbox");
|
||||
let labelName = doc.createElement("label");
|
||||
let labelValue = doc.createElement("label");
|
||||
labelName.className = "plain marker-details-labelname";
|
||||
labelValue.className = "plain marker-details-labelvalue";
|
||||
labelName.setAttribute("value", field);
|
||||
labelValue.setAttribute("value", value);
|
||||
hbox.appendChild(labelName);
|
||||
hbox.appendChild(labelValue);
|
||||
return hbox;
|
||||
},
|
||||
};
|
@ -19,6 +19,8 @@ loader.lazyImporter(this, "clearNamedTimeout",
|
||||
"resource:///modules/devtools/ViewHelpers.jsm");
|
||||
loader.lazyRequireGetter(this, "EventEmitter",
|
||||
"devtools/toolkit/event-emitter");
|
||||
loader.lazyRequireGetter(this, "MarkerUtils",
|
||||
"devtools/shared/timeline/marker-utils");
|
||||
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
@ -441,14 +443,7 @@ Waterfall.prototype = {
|
||||
name.setAttribute("flex", "1");
|
||||
name.className = "plain waterfall-marker-name";
|
||||
|
||||
let label;
|
||||
if (marker.causeName) {
|
||||
label = this._l10n.getFormatStr("timeline.markerDetailFormat",
|
||||
blueprint.label,
|
||||
marker.causeName);
|
||||
} else {
|
||||
label = blueprint.label;
|
||||
}
|
||||
let label = MarkerUtils.getMarkerLabel(marker);
|
||||
name.setAttribute("value", label);
|
||||
name.setAttribute("tooltiptext", label);
|
||||
sidebar.appendChild(name);
|
||||
|
@ -101,12 +101,32 @@
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
#performance-view .realtime-message {
|
||||
opacity: 0.5;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#performance-view toolbarbutton.record-button[checked],
|
||||
#performance-view toolbarbutton.record-button[checked] {
|
||||
color: var(--theme-selection-color);
|
||||
background: var(--theme-selection-background);
|
||||
}
|
||||
|
||||
#performance-view .realtime-disabled-message,
|
||||
#performance-view .realtime-disabled-on-e10s-message {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#performance-view[e10s="disabled"] .realtime-disabled-on-e10s-message {
|
||||
display: block;
|
||||
opacity: 0.5;
|
||||
|
||||
}
|
||||
#performance-view[e10s="unsupported"] .realtime-disabled-message {
|
||||
display: block;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#details-pane-container .buffer-status-message,
|
||||
#details-pane-container .buffer-status-message-full {
|
||||
display: none;
|
||||
@ -672,3 +692,35 @@
|
||||
background-image: url(chrome://browser/skin/devtools/webconsole@2x.png);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configurable Options
|
||||
*
|
||||
* Elements can be tagged with a class and visibility is controlled via a preference being
|
||||
* applied or removed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* devtools.performance.ui.experimental
|
||||
*/
|
||||
menuitem.experimental-option::before {
|
||||
content: "";
|
||||
background-image: url(chrome://browser/skin/devtools/webconsole.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 48px 40px;
|
||||
margin: 2px 5px 0 0;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
max-height: 8px;
|
||||
display: inline-block;
|
||||
background-position: -16px -16px;
|
||||
}
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
menuitem.experimental-option::before {
|
||||
background-image: url(chrome://browser/skin/devtools/webconsole@2x.png);
|
||||
}
|
||||
}
|
||||
#performance-options-menupopup:not(.experimental-enabled) .experimental-option,
|
||||
#performance-options-menupopup:not(.experimental-enabled) .experimental-option::before {
|
||||
display: none;
|
||||
}
|
||||
|
@ -25,4 +25,6 @@ dictionary ProfileTimelineMarker {
|
||||
unsigned short eventPhase;
|
||||
/* For Paint markers. */
|
||||
sequence<ProfileTimelineLayerRect> rectangles;
|
||||
/* For Style markers. */
|
||||
DOMString restyleHint;
|
||||
};
|
||||
|
@ -4186,7 +4186,6 @@ RestyleManager::StructsToLog()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
/* static */ nsCString
|
||||
RestyleManager::RestyleHintToString(nsRestyleHint aHint)
|
||||
{
|
||||
@ -4219,6 +4218,7 @@ RestyleManager::RestyleHintToString(nsRestyleHint aHint)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* static */ nsCString
|
||||
RestyleManager::ChangeHintToString(nsChangeHint aHint)
|
||||
{
|
||||
|
@ -348,8 +348,9 @@ public:
|
||||
mOverflowChangedTracker.Flush();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static nsCString RestyleHintToString(nsRestyleHint aHint);
|
||||
|
||||
#ifdef DEBUG
|
||||
static nsCString ChangeHintToString(nsChangeHint aHint);
|
||||
#endif
|
||||
|
||||
|
@ -96,6 +96,30 @@ struct RestyleCollector {
|
||||
#endif
|
||||
};
|
||||
|
||||
class RestyleTimelineMarker : public TimelineMarker
|
||||
{
|
||||
public:
|
||||
RestyleTimelineMarker(nsDocShell* aDocShell,
|
||||
TracingMetadata aMetaData,
|
||||
nsRestyleHint aRestyleHint)
|
||||
: TimelineMarker(aDocShell, "Styles", aMetaData)
|
||||
{
|
||||
if (aRestyleHint) {
|
||||
mRestyleHint.AssignWithConversion(RestyleManager::RestyleHintToString(aRestyleHint));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void AddDetails(mozilla::dom::ProfileTimelineMarker& aMarker) override
|
||||
{
|
||||
if (GetMetaData() == TRACING_INTERVAL_START) {
|
||||
aMarker.mRestyleHint.Construct(mRestyleHint);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoString mRestyleHint;
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
CollectRestyles(nsISupports* aElement,
|
||||
nsAutoPtr<RestyleTracker::RestyleData>& aData,
|
||||
@ -202,6 +226,13 @@ RestyleTracker::DoProcessRestyles()
|
||||
PROFILER_LABEL("RestyleTracker", "ProcessRestyles",
|
||||
js::ProfileEntry::Category::CSS);
|
||||
|
||||
bool isTimelineRecording = false;
|
||||
nsDocShell* docShell =
|
||||
static_cast<nsDocShell*>(mRestyleManager->PresContext()->GetDocShell());
|
||||
if (docShell) {
|
||||
docShell->GetRecordProfileTimelineMarkers(&isTimelineRecording);
|
||||
}
|
||||
|
||||
// Create a ReframingStyleContexts struct on the stack and put it in our
|
||||
// mReframingStyleContexts for almost all of the remaining scope of
|
||||
// this function.
|
||||
@ -311,6 +342,14 @@ RestyleTracker::DoProcessRestyles()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isTimelineRecording) {
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<RestyleTimelineMarker>(docShell,
|
||||
TRACING_INTERVAL_START,
|
||||
data->mRestyleHint);
|
||||
docShell->AddProfileTimelineMarker(Move(marker));
|
||||
}
|
||||
|
||||
#if defined(MOZ_ENABLE_PROFILER_SPS) && !defined(MOZILLA_XPCOMRT_API)
|
||||
Maybe<GeckoProfilerTracingRAII> profilerRAII;
|
||||
if (profiler_feature_active("restyle")) {
|
||||
@ -319,6 +358,14 @@ RestyleTracker::DoProcessRestyles()
|
||||
#endif
|
||||
ProcessOneRestyle(element, data->mRestyleHint, data->mChangeHint);
|
||||
AddRestyleRootsIfAwaitingRestyle(data->mDescendants);
|
||||
|
||||
if (isTimelineRecording) {
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<RestyleTimelineMarker>(docShell,
|
||||
TRACING_INTERVAL_END,
|
||||
data->mRestyleHint);
|
||||
docShell->AddProfileTimelineMarker(Move(marker));
|
||||
}
|
||||
}
|
||||
|
||||
if (mHaveLaterSiblingRestyles) {
|
||||
@ -359,9 +406,25 @@ RestyleTracker::DoProcessRestyles()
|
||||
profilerRAII.emplace("Paint", "Styles", Move(currentRestyle->mBacktrace));
|
||||
}
|
||||
#endif
|
||||
if (isTimelineRecording) {
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<RestyleTimelineMarker>(docShell,
|
||||
TRACING_INTERVAL_START,
|
||||
currentRestyle->mRestyleHint);
|
||||
docShell->AddProfileTimelineMarker(Move(marker));
|
||||
}
|
||||
|
||||
ProcessOneRestyle(currentRestyle->mElement,
|
||||
currentRestyle->mRestyleHint,
|
||||
currentRestyle->mChangeHint);
|
||||
|
||||
if (isTimelineRecording) {
|
||||
mozilla::UniquePtr<TimelineMarker> marker =
|
||||
MakeUnique<RestyleTimelineMarker>(docShell,
|
||||
TRACING_INTERVAL_END,
|
||||
currentRestyle->mRestyleHint);
|
||||
docShell->AddProfileTimelineMarker(Move(marker));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1656,11 +1656,6 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
|
||||
if (!mStyleFlushObservers.Contains(shell))
|
||||
continue;
|
||||
|
||||
nsRefPtr<nsDocShell> docShell = GetDocShell(shell->GetPresContext());
|
||||
if (docShell) {
|
||||
docShell->AddProfileTimelineMarker("Styles", TRACING_INTERVAL_START);
|
||||
}
|
||||
|
||||
if (!tracingStyleFlush) {
|
||||
tracingStyleFlush = true;
|
||||
profiler_tracing("Paint", "Styles", mStyleCause, TRACING_INTERVAL_START);
|
||||
@ -1679,10 +1674,6 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
|
||||
presContext->NotifyFontFaceSetOnRefresh();
|
||||
}
|
||||
NS_RELEASE(shell);
|
||||
|
||||
if (docShell) {
|
||||
docShell->AddProfileTimelineMarker("Styles", TRACING_INTERVAL_END);
|
||||
}
|
||||
}
|
||||
|
||||
if (tracingStyleFlush) {
|
||||
|
@ -485,7 +485,7 @@
|
||||
case KeyEvent.DOM_VK_BACK_SPACE:
|
||||
if (aEvent.shiftKey)
|
||||
#endif
|
||||
cancel = this.mController.handleDelete();
|
||||
cancel = this.handleDelete();
|
||||
break;
|
||||
case KeyEvent.DOM_VK_DOWN:
|
||||
case KeyEvent.DOM_VK_UP:
|
||||
@ -514,6 +514,12 @@
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="handleDelete">
|
||||
<body><![CDATA[
|
||||
return this.mController.handleDelete();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- ::::::::::::: miscellaneous ::::::::::::: -->
|
||||
|
||||
<method name="initSearchNames">
|
||||
|
Loading…
Reference in New Issue
Block a user