diff --git a/front_end/models/timeline_model/TimelineModelFilter.test.ts b/front_end/models/timeline_model/TimelineModelFilter.test.ts index 300de08818c..3393f51efd5 100644 --- a/front_end/models/timeline_model/TimelineModelFilter.test.ts +++ b/front_end/models/timeline_model/TimelineModelFilter.test.ts @@ -5,8 +5,14 @@ import {TraceLoader} from '../../testing/TraceLoader.js'; import * as TimelineModel from '../timeline_model/timeline_model.js'; import * as TraceEngine from '../trace/trace.js'; +import {initializeGlobalVars} from '../../testing/EnvironmentHelpers.js'; describe('TimelineModelFilter', () => { + before(async () => { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); + }); + describe('TimelineVisibleEventsFilter', () => { it('accepts events that are set in the constructor and rejects other events', async function() { const {traceData} = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); @@ -78,6 +84,11 @@ describe('TimelineModelFilter', () => { }); describe('ExclusiveNameFilter', () => { + before(async () => { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); + }); + it('accepts events that do not match the provided set of names to exclude', async function() { const {traceData} = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); const userTimingEvent = (traceData.UserTimings.performanceMeasures).at(0); diff --git a/front_end/models/trace/EntriesFilter.test.ts b/front_end/models/trace/EntriesFilter.test.ts index 8aae7b88cfc..9080df62e15 100644 --- a/front_end/models/trace/EntriesFilter.test.ts +++ b/front_end/models/trace/EntriesFilter.test.ts @@ -8,6 +8,7 @@ import {TraceLoader} from '../../testing/TraceLoader.js'; import * as TraceEngine from '../trace/trace.js'; +import {initializeGlobalVars} from '../../testing/EnvironmentHelpers.js'; function getMainThread(traceData: TraceEngine.Handlers.ModelHandlers.Renderer.RendererHandlerData): TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread { @@ -38,6 +39,11 @@ function findFirstEntry( } describe('EntriesFilter', function() { + before(async () => { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); + }); + it('parses a stack and returns an empty list of invisible entries', async function() { const {traceData} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); const stack = new TraceEngine.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); diff --git a/front_end/models/trace/handlers/RendererHandler.ts b/front_end/models/trace/handlers/RendererHandler.ts index bc4531250ca..c4be217bfbd 100644 --- a/front_end/models/trace/handlers/RendererHandler.ts +++ b/front_end/models/trace/handlers/RendererHandler.ts @@ -10,6 +10,7 @@ import {data as auctionWorkletsData} from './AuctionWorkletsHandler.js'; import {data as metaHandlerData, type FrameProcessData} from './MetaHandler.js'; import {data as samplesHandlerData} from './SamplesHandler.js'; import {HandlerState, type TraceEventHandlerName} from './types.js'; +import * as Root from '../../../core/root/root.js'; /** * This handler builds the hierarchy of trace events and profile calls @@ -23,6 +24,8 @@ import {HandlerState, type TraceEventHandlerName} from './types.js'; * event type. */ +let isReactNative: boolean; + const processes = new Map(); // We track the compositor tile worker thread name events so that at the end we @@ -80,6 +83,11 @@ export function initialize(): void { throw new Error('Renderer Handler was not reset'); } + // [RN] Used to scope down available features for React Native targets + isReactNative = Root.Runtime.experiments.isEnabled( + Root.Runtime.ExperimentName.REACT_NATIVE_SPECIFIC_UI, + ); + handlerState = HandlerState.INITIALIZED; } @@ -245,6 +253,11 @@ export function assignThreadName( * - Deletes processes with an unkonwn origin. */ export function sanitizeProcesses(processes: Map): void { + // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + if (isReactNative) { + return; + } + const auctionWorklets = auctionWorkletsData().worklets; const metaData = metaHandlerData(); if (metaData.traceIsGeneric) { diff --git a/front_end/models/trace/handlers/WarningsHandler.test.ts b/front_end/models/trace/handlers/WarningsHandler.test.ts index a2bbc08ebc4..8a71c445880 100644 --- a/front_end/models/trace/handlers/WarningsHandler.test.ts +++ b/front_end/models/trace/handlers/WarningsHandler.test.ts @@ -4,8 +4,14 @@ import {TraceLoader} from '../../../testing/TraceLoader.js'; import * as TraceEngine from '../trace.js'; +import {initializeGlobalVars} from '../../../testing/EnvironmentHelpers.js'; describe('WarningsHandler', function() { + before(async () => { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); + }); + beforeEach(() => { TraceEngine.Handlers.ModelHandlers.Warnings.reset(); }); diff --git a/front_end/models/trace/helpers/SyntheticEvents.test.ts b/front_end/models/trace/helpers/SyntheticEvents.test.ts index 689a528a02a..bdf2c9efb7d 100644 --- a/front_end/models/trace/helpers/SyntheticEvents.test.ts +++ b/front_end/models/trace/helpers/SyntheticEvents.test.ts @@ -4,8 +4,14 @@ import {TraceLoader} from '../../../testing/TraceLoader.js'; import * as TraceModel from '../trace.js'; +import {initializeGlobalVars} from '../../../testing/EnvironmentHelpers.js'; describe('SyntheticEvents', function() { + before(async () => { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); + }); + beforeEach(() => { TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.reset(); }); diff --git a/front_end/models/trace/insights/CumulativeLayoutShift.test.ts b/front_end/models/trace/insights/CumulativeLayoutShift.test.ts index c0a5d35d8ed..5a85f80c74a 100644 --- a/front_end/models/trace/insights/CumulativeLayoutShift.test.ts +++ b/front_end/models/trace/insights/CumulativeLayoutShift.test.ts @@ -8,6 +8,7 @@ import type * as TraceModel from '../trace.js'; import * as Types from '../types/types.js'; import {InsightRunners} from './insights.js'; +import {initializeGlobalVars} from '../../../testing/EnvironmentHelpers.js'; export async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) { const {traceData, insights} = await TraceLoader.traceEngine(testContext, traceFile); @@ -34,6 +35,11 @@ function getInsight(insights: TraceModel.Insights.Types.TraceInsightData, naviga const INVALIDATION_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5)); describe('CumulativeLayoutShift', function() { + before(async () => { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); + }); + describe('non composited animations', function() { it('gets the correct non composited animations', async function() { const {data, insights} = await processTrace(this, 'non-composited-animation.json.gz'); diff --git a/front_end/models/trace/insights/DocumentLatency.test.ts b/front_end/models/trace/insights/DocumentLatency.test.ts index 358034fcabe..4d2370c6247 100644 --- a/front_end/models/trace/insights/DocumentLatency.test.ts +++ b/front_end/models/trace/insights/DocumentLatency.test.ts @@ -5,6 +5,7 @@ import {TraceLoader} from '../../../testing/TraceLoader.js'; import * as TraceModel from '../trace.js'; import * as Types from '../types/types.js'; +import {initializeGlobalVars} from '../../../testing/EnvironmentHelpers.js'; export async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) { const {traceData, insights} = await TraceLoader.traceEngine(testContext, traceFile); @@ -28,6 +29,11 @@ function getInsight(insights: TraceModel.Insights.Types.TraceInsightData, naviga } describe('DocumentLatency', function() { + before(async () => { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); + }); + it('reports savings for main document with redirects', async () => { const {data, insights} = await processTrace(this, 'lantern/redirect/trace.json.gz'); const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); diff --git a/front_end/models/trace/insights/InteractionToNextPaint.test.ts b/front_end/models/trace/insights/InteractionToNextPaint.test.ts index 4dcd24b6c5c..0809be729e2 100644 --- a/front_end/models/trace/insights/InteractionToNextPaint.test.ts +++ b/front_end/models/trace/insights/InteractionToNextPaint.test.ts @@ -4,6 +4,7 @@ import {TraceLoader} from '../../../testing/TraceLoader.js'; import * as TraceModel from '../trace.js'; +import {initializeGlobalVars} from '../../../testing/EnvironmentHelpers.js'; export async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) { const {traceData, insights} = await TraceLoader.traceEngine(testContext, traceFile); @@ -15,6 +16,11 @@ export async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, } describe('InteractionToNextPaint', function() { + before(async () => { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); + }); + const test = (traceFile: string, longest?: number, highPercentile?: number) => { if (highPercentile === undefined) { highPercentile = longest; diff --git a/front_end/models/trace/insights/LargestContentfulPaint.test.ts b/front_end/models/trace/insights/LargestContentfulPaint.test.ts index 9a251957cb2..cc92271f41a 100644 --- a/front_end/models/trace/insights/LargestContentfulPaint.test.ts +++ b/front_end/models/trace/insights/LargestContentfulPaint.test.ts @@ -5,6 +5,7 @@ import {TraceLoader} from '../../../testing/TraceLoader.js'; import type * as TraceModel from '../trace.js'; import * as Types from '../types/types.js'; +import {initializeGlobalVars} from '../../../testing/EnvironmentHelpers.js'; export async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) { const {traceData, insights} = await TraceLoader.traceEngine(testContext, traceFile); @@ -28,6 +29,11 @@ function getInsight(insights: TraceModel.Insights.Types.TraceInsightData, naviga } describe('LargestContentfulPaint', function() { + before(async () => { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); + }); + it('text lcp phases', async () => { const {data, insights} = await processTrace(this, 'lcp-web-font.json.gz'); const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); diff --git a/front_end/models/trace/lantern/core/NetworkAnalyzer.test.ts b/front_end/models/trace/lantern/core/NetworkAnalyzer.test.ts index 7707ebe2393..80ca205bf05 100644 --- a/front_end/models/trace/lantern/core/NetworkAnalyzer.test.ts +++ b/front_end/models/trace/lantern/core/NetworkAnalyzer.test.ts @@ -7,6 +7,7 @@ import * as TraceModel from '../../trace.js'; import * as Lantern from '../lantern.js'; import {loadTrace, runTraceEngine} from '../testing/testing.js'; +import {initializeGlobalVars} from '../../../../testing/EnvironmentHelpers.js'; const {NetworkAnalyzer} = Lantern.Core; @@ -19,6 +20,8 @@ describe('NetworkAnalyzer', () => { let trace: Lantern.Types.Trace; let traceWithRedirect: Lantern.Types.Trace; before(async function() { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); trace = await loadTrace(this, 'lantern/paul/trace.json.gz'); traceWithRedirect = await loadTrace(this, 'lantern/redirect/trace.json.gz'); }); diff --git a/front_end/panels/timeline/Initiators.test.ts b/front_end/panels/timeline/Initiators.test.ts index 8e4e45f3a49..5261f142acc 100644 --- a/front_end/panels/timeline/Initiators.test.ts +++ b/front_end/panels/timeline/Initiators.test.ts @@ -4,10 +4,16 @@ import * as TraceEngine from '../../models/trace/trace.js'; import {TraceLoader} from '../../testing/TraceLoader.js'; +import {initializeGlobalVars} from '../../testing/EnvironmentHelpers.js'; import * as Timeline from './timeline.js'; describe('Initiators', () => { + before(async () => { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); + }); + it('returns the initiator data', async function() { const {traceData} = await TraceLoader.traceEngine(this, 'set-timeout-long-task.json.gz'); diff --git a/front_end/panels/timeline/ModificationsManager.test.ts b/front_end/panels/timeline/ModificationsManager.test.ts index 123fbbf47dc..12e054152b2 100644 --- a/front_end/panels/timeline/ModificationsManager.test.ts +++ b/front_end/panels/timeline/ModificationsManager.test.ts @@ -5,8 +5,14 @@ import type * as TraceEngine from '../../models/trace/trace.js'; import {TraceLoader} from '../../testing/TraceLoader.js'; import * as Timeline from './timeline.js'; +import {initializeGlobalVars} from '../../testing/EnvironmentHelpers.js'; describe('ModificationsManager', () => { + before(async () => { + // [RN] This will register required REACT_NATIVE_SPECIFIC_UI experiment. + await initializeGlobalVars(); + }); + it('applies modifications when present in a trace file', async function() { await TraceLoader.traceEngine(null, 'web-dev-modifications.json.gz'); const modificationsManager = Timeline.ModificationsManager.ModificationsManager.activeManager(); diff --git a/front_end/panels/timeline/TimelineFlameChartDataProvider.ts b/front_end/panels/timeline/TimelineFlameChartDataProvider.ts index 61b5f6201e1..c9658395da9 100644 --- a/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +++ b/front_end/panels/timeline/TimelineFlameChartDataProvider.ts @@ -80,6 +80,8 @@ export type TimelineFlameChartEntry = export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectWrapper implements PerfUI.FlameChart.FlameChartDataProvider { + private isReactNative: boolean = false; + private droppedFramePatternCanvas: HTMLCanvasElement; private partialFramePatternCanvas: HTMLCanvasElement; private timelineDataInternal: PerfUI.FlameChart.FlameChartTimelineData|null; @@ -114,6 +116,12 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW constructor() { super(); + + // [RN] Used to scope down available features for React Native targets + this.isReactNative = Root.Runtime.experiments.isEnabled( + Root.Runtime.ExperimentName.REACT_NATIVE_SPECIFIC_UI, + ); + this.reset(); this.#font = `${PerfUI.Font.DEFAULT_FONT_SIZE} ${PerfUI.Font.getFontFamilyForCanvas()}`; this.droppedFramePatternCanvas = document.createElement('canvas'); @@ -364,7 +372,10 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW #processInspectorTrace(): void { if (!this.isCpuProfile) { // CPU Profiles do not have frames and screenshots. - this.#appendFramesAndScreenshotsTrack(); + // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + if (!this.isReactNative) { + this.#appendFramesAndScreenshotsTrack(); + } } const weight = (track: {type?: string, forMainFrame?: boolean, appenderName?: TrackAppenderName}): number => { diff --git a/front_end/panels/timeline/TimelineLandingPage.ts b/front_end/panels/timeline/TimelineLandingPage.ts index ef61de45db5..9b1ae555a1d 100644 --- a/front_end/panels/timeline/TimelineLandingPage.ts +++ b/front_end/panels/timeline/TimelineLandingPage.ts @@ -48,11 +48,17 @@ interface Options { } export class TimelineLandingPage extends UI.Widget.VBox { + private readonly isReactNative: boolean = false; private readonly toggleRecordAction: UI.ActionRegistration.Action; constructor(toggleRecordAction: UI.ActionRegistration.Action, options?: Options) { super(); + // [RN] Used to scope down available features for React Native targets + this.isReactNative = Root.Runtime.experiments.isEnabled( + Root.Runtime.ExperimentName.REACT_NATIVE_SPECIFIC_UI, + ); + this.toggleRecordAction = toggleRecordAction; this.contentElement.classList.add('timeline-landing-page', 'fill'); @@ -83,7 +89,8 @@ export class TimelineLandingPage extends UI.Widget.VBox { const recordKey = encloseWithTag( 'b', UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutsForAction('timeline.toggle-recording')[0].title()); - const reloadKey = encloseWithTag( + // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + const reloadKey = this.isReactNative ? null : encloseWithTag( 'b', UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutsForAction('timeline.record-reload')[0].title()); const navigateNode = encloseWithTag('b', i18nString(UIStrings.wasd)); @@ -91,14 +98,18 @@ export class TimelineLandingPage extends UI.Widget.VBox { const centered = this.contentElement.createChild('div'); const recordButton = UI.UIUtils.createInlineButton(UI.Toolbar.Toolbar.createActionButton(this.toggleRecordAction)); - const reloadButton = + // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + const reloadButton = this.isReactNative ? null : UI.UIUtils.createInlineButton(UI.Toolbar.Toolbar.createActionButtonForId('timeline.record-reload')); centered.createChild('p').appendChild(i18n.i18n.getFormatLocalizedString( str_, UIStrings.clickTheRecordButtonSOrHitSTo, {PH1: recordButton, PH2: recordKey})); - centered.createChild('p').appendChild(i18n.i18n.getFormatLocalizedString( + // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + if (!this.isReactNative && reloadButton !== null && reloadKey !== null) { + centered.createChild('p').appendChild(i18n.i18n.getFormatLocalizedString( str_, UIStrings.clickTheReloadButtonSOrHitSTo, {PH1: reloadButton, PH2: reloadKey})); + } centered.createChild('p').appendChild(i18n.i18n.getFormatLocalizedString( str_, UIStrings.afterRecordingSelectAnAreaOf, {PH1: navigateNode, PH2: learnMoreNode})); diff --git a/front_end/panels/timeline/TimelinePanel.ts b/front_end/panels/timeline/TimelinePanel.ts index 1887e204737..d22a7658c7a 100644 --- a/front_end/panels/timeline/TimelinePanel.ts +++ b/front_end/panels/timeline/TimelinePanel.ts @@ -278,14 +278,16 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod private recordingPageReload: boolean; private readonly millisecondsToRecordAfterLoadEvent: number; private readonly toggleRecordAction: UI.ActionRegistration.Action; - private readonly recordReloadAction: UI.ActionRegistration.Action; + // Null for React Native entrypoints, see https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + private readonly recordReloadAction: UI.ActionRegistration.Action | null; readonly #historyManager: TimelineHistoryManager; private disableCaptureJSProfileSetting: Common.Settings.Setting; private readonly captureLayersAndPicturesSetting: Common.Settings.Setting; private readonly captureSelectorStatsSetting: Common.Settings.Setting; readonly #thirdPartyTracksSetting: Common.Settings.Setting; private showScreenshotsSetting: Common.Settings.Setting; - private showMemorySetting: Common.Settings.Setting; + // Null for React Native entrypoints, see https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + private showMemorySetting: Common.Settings.Setting | null; private readonly panelToolbar: UI.Toolbar.Toolbar; private readonly panelRightToolbar: UI.Toolbar.Toolbar; private readonly timelinePane: UI.Widget.VBox; @@ -362,7 +364,8 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod this.recordingPageReload = false; this.millisecondsToRecordAfterLoadEvent = 5000; this.toggleRecordAction = UI.ActionRegistry.ActionRegistry.instance().getAction('timeline.toggle-recording'); - this.recordReloadAction = UI.ActionRegistry.ActionRegistry.instance().getAction('timeline.record-reload'); + // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + this.recordReloadAction = isReactNative ? null : UI.ActionRegistry.ActionRegistry.instance().getAction('timeline.record-reload'); this.#historyManager = new TimelineHistoryManager(this.#minimapComponent); @@ -383,9 +386,14 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod this.showScreenshotsSetting.setTitle(i18nString(UIStrings.screenshots)); this.showScreenshotsSetting.addChangeListener(this.updateMiniMap, this); - this.showMemorySetting = Common.Settings.Settings.instance().createSetting('timeline-show-memory', false); - this.showMemorySetting.setTitle(i18nString(UIStrings.memory)); - this.showMemorySetting.addChangeListener(this.onModeChanged, this); + // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + if (isReactNative) { + this.showMemorySetting = null; + } else { + this.showMemorySetting = Common.Settings.Settings.instance().createSetting('timeline-show-memory', false); + this.showMemorySetting.setTitle(i18nString(UIStrings.memory)); + this.showMemorySetting.addChangeListener(this.onModeChanged, this); + } this.#thirdPartyTracksSetting = TimelinePanel.extensionDataVisibilitySetting(); this.#thirdPartyTracksSetting.addChangeListener(this.#extensionDataVisibilityChanged, this); @@ -637,7 +645,10 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod private populateToolbar(): void { // Record this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.toggleRecordAction)); - this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.recordReloadAction)); + // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + if (!isReactNative && this.recordReloadAction !== null) { + this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.recordReloadAction)); + } this.clearButton = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.clear), 'clear'); this.clearButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, () => this.onClearButton()); this.panelToolbar.appendToolbarItem(this.clearButton); @@ -695,9 +706,12 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod this.panelToolbar.appendToolbarItem(this.showScreenshotsToolbarCheckbox); } - this.showMemoryToolbarCheckbox = + // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + if (!isReactNative && this.showMemorySetting !== null) { + this.showMemoryToolbarCheckbox = this.createSettingCheckbox(this.showMemorySetting, i18nString(UIStrings.showMemoryTimeline)); - this.panelToolbar.appendToolbarItem(this.showMemoryToolbarCheckbox); + this.panelToolbar.appendToolbarItem(this.showMemoryToolbarCheckbox); + } // GC this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButtonForId('components.collect-garbage')); @@ -948,13 +962,14 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod isCpuProfile, settings: { showScreenshots: this.showScreenshotsSetting.get(), - showMemory: this.showMemorySetting.get(), + showMemory: !isReactNative && this.showMemorySetting !== null && this.showMemorySetting.get(), // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. }, }); } private onModeChanged(): void { - this.flameChart.updateCountersGraphToggle(this.showMemorySetting.get()); + // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + this.flameChart.updateCountersGraphToggle(!isReactNative && this.showMemorySetting !== null && this.showMemorySetting.get()); this.updateMiniMap(); this.doResize(); this.select(null); @@ -1250,7 +1265,10 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod private updateTimelineControls(): void { this.toggleRecordAction.setToggled(this.state === State.Recording); this.toggleRecordAction.setEnabled(this.state === State.Recording || this.state === State.Idle); - this.recordReloadAction.setEnabled(isNode ? false : this.state === State.Idle); + // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. + if (!isReactNative && this.recordReloadAction !== null) { + this.recordReloadAction.setEnabled(isNode ? false : this.state === State.Idle); + } this.#historyManager.setEnabled(this.state === State.Idle); this.clearButton.setEnabled(this.state === State.Idle); this.panelToolbar.setEnabled(this.state !== State.Loading); diff --git a/front_end/panels/timeline/timeline-meta.ts b/front_end/panels/timeline/timeline-meta.ts index 436d57fe15d..affda660cf6 100644 --- a/front_end/panels/timeline/timeline-meta.ts +++ b/front_end/panels/timeline/timeline-meta.ts @@ -152,6 +152,7 @@ UI.ActionRegistration.registerActionExtension({ shortcut: 'Meta+Shift+E', }, ], + experiment: Root.Runtime.ExperimentName.REACT_NATIVE_SPECIFIC_UI, // See https://docs.google.com/document/d/1_mtLIHEd9bFQN4xWBSVDR357GaRo56khB1aOxgWDeu4/edit?tab=t.0 for context. }); UI.ActionRegistration.registerActionExtension({