chrome-devtools-frontend
Version:
Chrome DevTools UI
416 lines (390 loc) • 15.2 kB
text/typescript
// Copyright 2023 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import type * as Platform from '../../../../core/platform/platform.js';
import * as Trace from '../../../../models/trace/trace.js';
import * as Extensions from '../../../../panels/timeline/extensions/extensions.js';
import * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js';
import * as TraceHelpers from '../../../../testing/TraceHelpers.js';
import * as PerfUI from '../../../legacy/components/perf_ui/perf_ui.js';
import * as ComponentSetup from '../../helpers/helpers.js';
await EnvironmentHelpers.initializeGlobalVars();
await ComponentSetup.ComponentServerSetup.setup();
const defaultGroupStyle = {
height: 17,
padding: 4,
collapsible: false,
color: 'black',
backgroundColor: 'grey',
nestingLevel: 0,
itemsHeight: 17,
};
/**
* Render a basic flame chart with 3 events on the same level
**/
function renderBasicExample() {
class FakeProviderWithBasicEvents extends TraceHelpers.FakeFlameChartProvider {
override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {
return PerfUI.FlameChart.FlameChartTimelineData.create({
entryLevels: [0, 0, 0, 1, 1, 1, 2, 2, 2],
entryStartTimes: [5, 60, 80, 5, 60, 80, 5, 60, 80],
entryTotalTimes: [50, 10, 10, 50, 10, 10, 50, 10, 10],
groups: [
{
name: 'Test Group 0' as Platform.UIString.LocalizedString,
startLevel: 0,
style: {...defaultGroupStyle, collapsible: true},
},
{
name: 'Test Group 1' as Platform.UIString.LocalizedString,
startLevel: 1,
style: {...defaultGroupStyle, collapsible: true, color: 'red', backgroundColor: 'green'},
},
{
name: 'Test Group 2' as Platform.UIString.LocalizedString,
startLevel: 2,
style: {...defaultGroupStyle, collapsible: true, color: 'blue', backgroundColor: 'yellow'},
},
],
});
}
}
const container = document.querySelector('div#basic');
if (!container) {
throw new Error('No container');
}
const delegate = new TraceHelpers.MockFlameChartDelegate();
const dataProvider = new FakeProviderWithBasicEvents();
const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);
flameChart.markAsRoot();
flameChart.setWindowTimes(0, 100);
flameChart.show(container);
flameChart.update();
}
/**
* Render a flame chart with events with decorations.
**/
function renderDecorationExample() {
class FakeProviderWithDecorations extends TraceHelpers.FakeFlameChartProvider {
override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {
return PerfUI.FlameChart.FlameChartTimelineData.create({
entryLevels: [0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2],
entryStartTimes: [5, 55, 70, 5, 30, 55, 75, 5, 10, 15, 20, 25],
entryTotalTimes: [45, 10, 20, 20, 20, 5, 15, 4, 4, 4, 4, 1],
entryDecorations: [
[
{
type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,
startAtTime: Trace.Types.Timing.Micro(25_000),
},
{type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},
],
[{type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE}],
[
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
{type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},
],
[
{
type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,
startAtTime: Trace.Types.Timing.Micro(15_000),
},
],
[
{
type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,
startAtTime: Trace.Types.Timing.Micro(10_000),
},
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
],
[
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
],
[
{
type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,
startAtTime: Trace.Types.Timing.Micro(10_000),
},
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
{type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},
],
[
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
],
[
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
{type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},
],
[
{
type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,
startAtTime: Trace.Types.Timing.Micro(1_000),
},
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
],
[
{
type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,
startAtTime: Trace.Types.Timing.Micro(1_000),
},
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
{type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},
],
[
{
type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE,
// This triangle should start 1/4 of hte event, and end at 3/4 of the event.
customStartTime: Trace.Types.Timing.Micro(25_250),
customEndTime: Trace.Types.Timing.Micro(25_750),
},
],
],
groups: [{
name: 'Testing Candy Stripe, warning triangles and hidden descendants arrow decorations' as
Platform.UIString.LocalizedString,
startLevel: 0,
style: defaultGroupStyle,
}],
});
}
}
const container = document.querySelector('div#decorations');
if (!container) {
throw new Error('No container');
}
const delegate = new TraceHelpers.MockFlameChartDelegate();
const dataProvider = new FakeProviderWithDecorations();
const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);
flameChart.markAsRoot();
flameChart.setWindowTimes(0, 100);
flameChart.show(container);
flameChart.update();
}
/**
* Render a flame chart with nested track.
**/
function renderNestedExample() {
class FakeProviderWithNestedGroup extends TraceHelpers.FakeFlameChartProvider {
override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {
return PerfUI.FlameChart.FlameChartTimelineData.create({
entryLevels: [0, 1, 2],
entryStartTimes: [5, 5, 5],
entryTotalTimes: [50, 50, 50],
groups: [
{
name: 'Test Group 0' as Platform.UIString.LocalizedString,
startLevel: 0,
style: {...defaultGroupStyle, collapsible: true},
},
{
name: 'Test Nested Group 1' as Platform.UIString.LocalizedString,
startLevel: 0,
style: {...defaultGroupStyle, collapsible: true, color: 'red', backgroundColor: 'green'},
},
{
name: 'Test Group 2' as Platform.UIString.LocalizedString,
startLevel: 2,
style: {...defaultGroupStyle, collapsible: true, color: 'blue', backgroundColor: 'yellow'},
},
],
});
}
}
const container = document.querySelector('div#nested');
if (!container) {
throw new Error('No container');
}
const delegate = new TraceHelpers.MockFlameChartDelegate();
const dataProvider = new FakeProviderWithNestedGroup();
const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);
flameChart.markAsRoot();
flameChart.setWindowTimes(0, 100);
flameChart.show(container);
flameChart.update();
}
/**
* Render a flame chart with nested case and buttons to hide/unhide and reorder
* tracks
**/
function renderTrackCustomizationExample() {
class FakeProviderWithBasicEvents extends TraceHelpers.FakeFlameChartProvider {
override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {
return PerfUI.FlameChart.FlameChartTimelineData.create({
entryLevels: [0, 0, 1, 1, 2, 2, 3, 3],
entryStartTimes: [5, 60, 5, 60, 5, 60],
entryTotalTimes: [50, 10, 50, 10, 50, 10],
groups: [
{
name: 'Test Group 0' as Platform.UIString.LocalizedString,
startLevel: 0,
expanded: true,
style: {...defaultGroupStyle, collapsible: true},
},
{
name: 'Test Group 1' as Platform.UIString.LocalizedString,
startLevel: 1,
expanded: true,
style: {...defaultGroupStyle, collapsible: true, color: 'red', backgroundColor: 'green'},
},
{
name: 'Test Group 2' as Platform.UIString.LocalizedString,
startLevel: 2,
expanded: true,
style: {...defaultGroupStyle, collapsible: true, color: 'blue', backgroundColor: 'yellow'},
},
{
name: 'Test Group 3' as Platform.UIString.LocalizedString,
startLevel: 2,
expanded: true,
style: {...defaultGroupStyle, nestingLevel: 1},
},
],
});
}
}
const container = document.querySelector('div#track-customization');
if (!container) {
throw new Error('No container');
}
const delegate = new TraceHelpers.MockFlameChartDelegate();
const dataProvider = new FakeProviderWithBasicEvents();
const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);
flameChart.markAsRoot();
flameChart.setWindowTimes(0, 100);
flameChart.show(container);
flameChart.update();
const indexInput = document.querySelector('#indexOfTrack') as HTMLInputElement;
const buttonHide = document.querySelector('#hide');
buttonHide?.addEventListener('click', () => {
const index = Number(indexInput.value);
flameChart.hideGroup(index);
});
const buttonUnhide = document.querySelector('#unhide');
buttonUnhide?.addEventListener('click', () => {
const index = Number(indexInput.value);
flameChart.showGroup(index);
});
const buttonForMoveUp = document.querySelector('#testForMoveUp');
buttonForMoveUp?.addEventListener('click', () => {
const index = Number(indexInput.value);
flameChart.moveGroupUp(index);
});
const buttonForMoveDown = document.querySelector('#testForMoveDown');
buttonForMoveDown?.addEventListener('click', () => {
const index = Number(indexInput.value);
flameChart.moveGroupDown(index);
});
}
/**
* Render a flame chart with event initiators of different sizes.
* Some initiator and initiated events are hidden.
**/
function renderInitiatorsExample() {
class FakeProviderWithVariousTasksForInitiators extends TraceHelpers.FakeFlameChartProvider {
override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {
return PerfUI.FlameChart.FlameChartTimelineData.create({
entryLevels: [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 3],
entryStartTimes: [5, 5, 5, 15, 15, 15, 40, 40, 40, 55.4, 55.4, 55.4, 80, 80, 80, 17],
entryTotalTimes: [6, 6, 6, 5, 5, 20, 15, 15, 15, 2, 2, 2, 10, 10, 10, 10],
entryDecorations: [
[],
[],
[
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
],
[],
[],
[],
[],
[],
[
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
],
[],
[],
[
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
],
[
{type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},
],
],
initiatorsData: [
{initiatorIndex: 2, eventIndex: 3, isInitiatorHidden: true},
{initiatorIndex: 1, eventIndex: 13},
{initiatorIndex: 3, eventIndex: 6},
{initiatorIndex: 3, eventIndex: 8, isEntryHidden: true},
{initiatorIndex: 6, eventIndex: 11},
{initiatorIndex: 11, eventIndex: 12, isInitiatorHidden: true, isEntryHidden: true},
{initiatorIndex: 5, eventIndex: 15},
],
groups: [{
name: 'Testing initiators' as Platform.UIString.LocalizedString,
startLevel: 0,
style: defaultGroupStyle,
}],
});
}
override maxStackDepth(): number {
return 4;
}
}
const container = document.querySelector('div#initiators');
if (!container) {
throw new Error('No container');
}
const delegate = new TraceHelpers.MockFlameChartDelegate();
const dataProvider = new FakeProviderWithVariousTasksForInitiators();
const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);
flameChart.markAsRoot();
flameChart.setSelectedEntry(14);
flameChart.setWindowTimes(0, 100);
flameChart.show(container);
flameChart.update();
}
/**
* Used to test the color palette for extension events
*/
function renderExtensionTrackExample() {
const colorPalette = Trace.Types.Extensions.extensionPalette;
const paletteLength = colorPalette.length;
class FakeProviderWithExtensionColors extends TraceHelpers.FakeFlameChartProvider {
override entryColor(entryIndex: number): string {
const color = colorPalette[entryIndex % paletteLength];
return Extensions.ExtensionUI.extensionEntryColor(
{args: {color}} as Trace.Types.Extensions.SyntheticExtensionEntry);
}
override maxStackDepth(): number {
return paletteLength + 1;
}
override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {
return PerfUI.FlameChart.FlameChartTimelineData.create({
entryLevels: colorPalette.map((_, i) => i),
entryStartTimes: colorPalette.map(() => 0),
entryTotalTimes: colorPalette.map(() => 100),
groups: [{
name: 'Testing extension palette' as Platform.UIString.LocalizedString,
startLevel: 0,
style: defaultGroupStyle,
}],
});
}
}
const container = document.querySelector('div#extension');
if (!container) {
throw new Error('No container');
}
const delegate = new TraceHelpers.MockFlameChartDelegate();
const dataProvider = new FakeProviderWithExtensionColors();
const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);
flameChart.markAsRoot();
flameChart.setWindowTimes(0, 100);
flameChart.show(container);
flameChart.update();
}
renderBasicExample();
renderDecorationExample();
renderNestedExample();
renderTrackCustomizationExample();
renderInitiatorsExample();
renderExtensionTrackExample();