UNPKG

chrome-devtools-frontend

Version:
149 lines (127 loc) 5.58 kB
// Copyright 2014 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js'; import type * as Protocol from '../../generated/protocol.js'; import * as i18n from '../i18n/i18n.js'; import {DebuggerModel, Location} from './DebuggerModel.js'; import type {RuntimeModel} from './RuntimeModel.js'; import {SDKModel} from './SDKModel.js'; import {Capability, type Target} from './Target.js'; const UIStrings = { /** * @description Name of a profile. Placeholder is either a user-supplied name or a number automatically assigned to the profile. * @example {2} PH1 */ profileD: 'Profile {PH1}', } as const; const str_ = i18n.i18n.registerUIStrings('core/sdk/CPUProfilerModel.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export class CPUProfilerModel extends SDKModel<EventTypes> implements ProtocolProxyApi.ProfilerDispatcher { #nextAnonymousConsoleProfileNumber: number; #anonymousConsoleProfileIdToTitle: Map<string, string>; readonly #profilerAgent: ProtocolProxyApi.ProfilerApi; #preciseCoverageDeltaUpdateCallback: ((arg0: number, arg2: Protocol.Profiler.ScriptCoverage[]) => Promise<void>)|null; readonly #debuggerModel: DebuggerModel; readonly registeredConsoleProfileMessages: ProfileFinishedData[] = []; constructor(target: Target) { super(target); this.#nextAnonymousConsoleProfileNumber = 1; this.#anonymousConsoleProfileIdToTitle = new Map(); this.#profilerAgent = target.profilerAgent(); this.#preciseCoverageDeltaUpdateCallback = null; target.registerProfilerDispatcher(this); void this.#profilerAgent.invoke_enable(); this.#debuggerModel = (target.model(DebuggerModel) as DebuggerModel); } runtimeModel(): RuntimeModel { return this.#debuggerModel.runtimeModel(); } debuggerModel(): DebuggerModel { return this.#debuggerModel; } consoleProfileStarted({id, location, title}: Protocol.Profiler.ConsoleProfileStartedEvent): void { if (!title) { title = i18nString(UIStrings.profileD, {PH1: this.#nextAnonymousConsoleProfileNumber++}); this.#anonymousConsoleProfileIdToTitle.set(id, title); } const eventData = this.createEventDataFrom(id, location, title); this.dispatchEventToListeners(Events.CONSOLE_PROFILE_STARTED, eventData); } consoleProfileFinished({id, location, profile, title}: Protocol.Profiler.ConsoleProfileFinishedEvent): void { if (!title) { title = this.#anonymousConsoleProfileIdToTitle.get(id); this.#anonymousConsoleProfileIdToTitle.delete(id); } const eventData: ProfileFinishedData = { ...this.createEventDataFrom(id, location, title), cpuProfile: profile, }; this.registeredConsoleProfileMessages.push(eventData); this.dispatchEventToListeners(Events.CONSOLE_PROFILE_FINISHED, eventData); } private createEventDataFrom(id: string, scriptLocation: Protocol.Debugger.Location, title?: string): EventData { const debuggerLocation = Location.fromPayload(this.#debuggerModel, scriptLocation); const globalId = this.target().id() + '.' + id; return { id: globalId, scriptLocation: debuggerLocation, title: title || '', cpuProfilerModel: this, }; } startRecording(): Promise<unknown> { const intervalUs = 100; void this.#profilerAgent.invoke_setSamplingInterval({interval: intervalUs}); return this.#profilerAgent.invoke_start(); } stopRecording(): Promise<Protocol.Profiler.Profile|null> { return this.#profilerAgent.invoke_stop().then(response => response.profile || null); } startPreciseCoverage( jsCoveragePerBlock: boolean, preciseCoverageDeltaUpdateCallback: ((arg0: number, arg2: Protocol.Profiler.ScriptCoverage[]) => Promise<void>)| null): Promise<unknown> { const callCount = false; this.#preciseCoverageDeltaUpdateCallback = preciseCoverageDeltaUpdateCallback; const allowUpdatesTriggeredByBackend = true; return this.#profilerAgent.invoke_startPreciseCoverage( {callCount, detailed: jsCoveragePerBlock, allowTriggeredUpdates: allowUpdatesTriggeredByBackend}); } async takePreciseCoverage(): Promise<{ timestamp: number, coverage: Protocol.Profiler.ScriptCoverage[], }> { const r = await this.#profilerAgent.invoke_takePreciseCoverage(); const timestamp = (r?.timestamp) || 0; const coverage = (r?.result) || []; return {timestamp, coverage}; } stopPreciseCoverage(): Promise<unknown> { this.#preciseCoverageDeltaUpdateCallback = null; return this.#profilerAgent.invoke_stopPreciseCoverage(); } preciseCoverageDeltaUpdate({timestamp, result}: Protocol.Profiler.PreciseCoverageDeltaUpdateEvent): void { if (this.#preciseCoverageDeltaUpdateCallback) { void this.#preciseCoverageDeltaUpdateCallback(timestamp, result); } } } export const enum Events { CONSOLE_PROFILE_STARTED = 'ConsoleProfileStarted', CONSOLE_PROFILE_FINISHED = 'ConsoleProfileFinished', } export interface EventTypes { [Events.CONSOLE_PROFILE_STARTED]: EventData; [Events.CONSOLE_PROFILE_FINISHED]: ProfileFinishedData; } SDKModel.register(CPUProfilerModel, {capabilities: Capability.JS, autostart: true}); export interface EventData { id: string; scriptLocation: Location; title: string; cpuProfilerModel: CPUProfilerModel; } export interface ProfileFinishedData extends EventData { cpuProfile: Protocol.Profiler.Profile; }